diff --git a/DEPS b/DEPS
index 88f33bc..b3e979a6 100644
--- a/DEPS
+++ b/DEPS
@@ -245,15 +245,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': 'bc1e97ee5f64956562f53f0561035a213aca563f',
+  'skia_revision': 'eccf8a03ad73f7c1d9a8e7873844837105c4d2d6',
   # 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': '9614ec2f1f074c0f3f2107065089e905d8329b8e',
+  'v8_revision': '8f934dfb5a9bc90998d220a0918f306df23211fc',
   # 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': 'fe56532f503c9a6acde95f7573d705468102faff',
+  'angle_revision': '57933493dd3bc21214ba351ad4e44b60efffe711',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -276,7 +276,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling googletest
   # and whatever else without interference from each other.
-  'googletest_revision': '4517697675fc0d51c89aca61af5c77c4f1e4ee2d',
+  'googletest_revision': '25ad42aabeaba6227f37795cdd2752e128e83827',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lighttpd
   # and whatever else without interference from each other.
@@ -320,7 +320,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': 'd42fdfb2fb377e121bdb39699d5a8cfb5c4a0d27',
+  'devtools_frontend_revision': '2b8d9b85fe747dbff37b87f946ada6a947096399',
   # 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.
@@ -360,7 +360,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': '38f2ff52dd9e7a0f64ff8f05022d078aa855798d',
+  'dawn_revision': '0123832cc0031d89a5130d92fe913b914a3bc5e3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -408,7 +408,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libunwind_revision':    'd0ad43c5e10e732958f2d5ff4ae0b79f78506fcf',
+  'libunwind_revision':    '659c7d91af58bfeada9f3ed5bf1a192059b68b86',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -687,7 +687,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e4d2180ce273bd52cb897491904f0293391be33b',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e4df9e3aa8ff0fa7c2170a8e23f308406a483230',
       'condition': 'checkout_ios',
   },
 
@@ -1085,7 +1085,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '492176b4978fec301855a31a41e19ea0923bf762',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '1f04886f43223eccb668573b77aab0bc2f66fec5',
       'condition': 'checkout_linux',
   },
 
@@ -1473,7 +1473,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c388978ab5ee678b31251d5615403bbae949528e',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '098713f3622cb18d3bb7828fdc690b323487fefe',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1655,7 +1655,7 @@
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb',
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@b815f299c1fb2192580711e32525a19936abfd81',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@fe093f4789c21b9d5efa2c65c00df4ac5ea53234',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1691,10 +1691,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '89f20c5e69574ffbede2d89e18b4dba71bf9c1f2',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '1643a2fe7b56eb2b65b4dcded355fd2453555df4',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '608e381b4d770d58d13fab8e2fd068f6e62d0950',
+    Var('webrtc_git') + '/src.git' + '@' + 'c79dc98a600cc5a6fd278ac62103613a55771945',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1764,7 +1764,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f4207693f8e05a6c67858770ba5a025c42bd0a97',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0a7cc35765b595ba2b09f2f65b90089d07b2d872',
     'condition': 'checkout_src_internal',
   },
 
@@ -1816,7 +1816,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'wFuE5knwvc-B3G4vWb5M348dskZwglL_s7oxGyabyiIC',
+        'version': '_-MeoCCkeQeoTZdmNg_os9nIKbT1IVHKmu3qyyuUensC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn
index 6b22190e..43111a7 100644
--- a/ash/components/arc/BUILD.gn
+++ b/ash/components/arc/BUILD.gn
@@ -120,6 +120,8 @@
     "//chromeos/components/sensors:sensors",
     "//chromeos/dbus",
     "//chromeos/dbus/cryptohome",
+    "//chromeos/dbus/patchpanel",
+    "//chromeos/dbus/patchpanel:patchpanel_proto",
     "//chromeos/dbus/permission_broker",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
@@ -429,6 +431,8 @@
     "//chromeos",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/dlcservice",
+    "//chromeos/dbus/patchpanel",
+    "//chromeos/dbus/patchpanel:patchpanel_proto",
     "//chromeos/dbus/permission_broker",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc
index a3a05ca..d96a5ea 100644
--- a/ash/components/arc/net/arc_net_host_impl.cc
+++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -4,6 +4,8 @@
 
 #include "ash/components/arc/net/arc_net_host_impl.h"
 
+#include <net/if.h>
+
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -16,6 +18,8 @@
 #include "base/memory/singleton.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/string_number_conversions.h"
+#include "chromeos/dbus/patchpanel/patchpanel_client.h"
+#include "chromeos/dbus/patchpanel/patchpanel_service.pb.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/device_state.h"
@@ -60,7 +64,7 @@
       chromeos::LoginState::Get()->primary_user_hash());
 }
 
-std::vector<const chromeos::NetworkState*> GetActiveNetworks() {
+std::vector<const chromeos::NetworkState*> GetHostActiveNetworks() {
   std::vector<const chromeos::NetworkState*> active_networks;
   GetStateHandler()->GetActiveNetworkListByType(
       chromeos::NetworkTypePattern::Default(), &active_networks);
@@ -354,12 +358,31 @@
   return GetStateHandler()->GetNetworkStateFromGuid(network->tether_guid());
 }
 
+std::string IPv4AddressToString(uint32_t addr) {
+  char buf[INET_ADDRSTRLEN] = {0};
+  struct in_addr ia;
+  ia.s_addr = addr;
+  return !inet_ntop(AF_INET, &ia, buf, sizeof(buf)) ? std::string() : buf;
+}
+
 // Convenience helper for translating a vector of NetworkState objects to a
 // vector of mojo NetworkConfiguration objects.
 std::vector<arc::mojom::NetworkConfigurationPtr> TranslateNetworkStates(
     const std::string& arc_vpn_path,
     const chromeos::NetworkStateHandler::NetworkStateList& network_states,
-    const std::map<std::string, base::Value>& shill_network_properties) {
+    const std::map<std::string, base::Value>& shill_network_properties,
+    const std::vector<patchpanel::NetworkDevice>& devices) {
+  // Move the devices vector to a map keyed by its physical interface name in
+  // order to avoid multiple loops. The map also filters non-ARC devices.
+  std::map<std::string, patchpanel::NetworkDevice> arc_devices;
+  for (const auto& d : devices) {
+    if (d.guest_type() != patchpanel::NetworkDevice::ARC &&
+        d.guest_type() != patchpanel::NetworkDevice::ARCVM) {
+      continue;
+    }
+    arc_devices.emplace(d.phys_ifname(), d);
+  }
+
   std::vector<arc::mojom::NetworkConfigurationPtr> networks;
   for (const chromeos::NetworkState* state : network_states) {
     const std::string& network_path = state->path();
@@ -381,6 +404,19 @@
     auto network = TranslateNetworkProperties(state, shill_dict);
     network->is_default_network = state == GetStateHandler()->DefaultNetwork();
     network->service_name = network_path;
+
+    // Fill in ARC properties.
+    auto arc_it =
+        arc_devices.find(network->network_interface.value_or(std::string()));
+    if (arc_it != arc_devices.end()) {
+      network->arc_network_interface = arc_it->second.guest_ifname();
+      network->arc_ipv4_address =
+          IPv4AddressToString(arc_it->second.ipv4_addr());
+      network->arc_ipv4_gateway =
+          IPv4AddressToString(arc_it->second.host_ipv4_addr());
+      network->arc_ipv4_prefix_length =
+          arc_it->second.ipv4_subnet().prefix_len();
+    }
     networks.push_back(std::move(network));
   }
   return networks;
@@ -532,25 +568,41 @@
 void ArcNetHostImpl::GetNetworks(mojom::GetNetworksRequestType type,
                                  GetNetworksCallback callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  chromeos::NetworkStateHandler::NetworkStateList network_states;
   if (type == mojom::GetNetworksRequestType::ACTIVE_ONLY) {
-    // Retrieve list of currently active networks.
-    GetStateHandler()->GetActiveNetworkListByType(
-        chromeos::NetworkTypePattern::Default(), &network_states);
-  } else {
-    // Otherwise retrieve list of configured or visible WiFi networks.
-    bool configured_only =
-        type == mojom::GetNetworksRequestType::CONFIGURED_ONLY;
-    chromeos::NetworkTypePattern network_pattern =
-        chromeos::onc::NetworkTypePatternFromOncType(onc::network_type::kWiFi);
-    GetStateHandler()->GetNetworkListByType(
-        network_pattern, configured_only, !configured_only /* visible_only */,
-        kGetNetworksListLimit, &network_states);
+    chromeos::PatchPanelClient::Get()->GetDevices(
+        base::BindOnce(&ArcNetHostImpl::GetActiveNetworks,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+    return;
   }
 
-  std::vector<mojom::NetworkConfigurationPtr> networks = TranslateNetworkStates(
-      arc_vpn_service_path_, network_states, shill_network_properties_);
+  // Otherwise retrieve list of configured or visible WiFi networks.
+  bool configured_only = type == mojom::GetNetworksRequestType::CONFIGURED_ONLY;
+  chromeos::NetworkTypePattern network_pattern =
+      chromeos::onc::NetworkTypePatternFromOncType(onc::network_type::kWiFi);
+
+  chromeos::NetworkStateHandler::NetworkStateList network_states;
+  GetStateHandler()->GetNetworkListByType(
+      network_pattern, configured_only, !configured_only /* visible_only */,
+      kGetNetworksListLimit, &network_states);
+
+  std::vector<mojom::NetworkConfigurationPtr> networks =
+      TranslateNetworkStates(arc_vpn_service_path_, network_states,
+                             shill_network_properties_, {} /* devices */);
+  std::move(callback).Run(mojom::GetNetworksResponseType::New(
+      arc::mojom::NetworkResult::SUCCESS, std::move(networks)));
+}
+
+void ArcNetHostImpl::GetActiveNetworks(
+    GetNetworksCallback callback,
+    const std::vector<patchpanel::NetworkDevice>& devices) {
+  // Retrieve list of currently active networks.
+  chromeos::NetworkStateHandler::NetworkStateList network_states;
+  GetStateHandler()->GetActiveNetworkListByType(
+      chromeos::NetworkTypePattern::Default(), &network_states);
+
+  std::vector<mojom::NetworkConfigurationPtr> networks =
+      TranslateNetworkStates(arc_vpn_service_path_, network_states,
+                             shill_network_properties_, devices);
   std::move(callback).Run(mojom::GetNetworksResponseType::New(
       arc::mojom::NetworkResult::SUCCESS, std::move(networks)));
 }
@@ -1089,17 +1141,22 @@
     return;
 
   shill_network_properties_[service_path] = std::move(*shill_properties);
-  UpdateActiveNetworks();
+
+  // Get patchpanel devices and update active networks.
+  chromeos::PatchPanelClient::Get()->GetDevices(base::BindOnce(
+      &ArcNetHostImpl::UpdateActiveNetworks, weak_factory_.GetWeakPtr()));
 }
 
-void ArcNetHostImpl::UpdateActiveNetworks() {
+void ArcNetHostImpl::UpdateActiveNetworks(
+    const std::vector<patchpanel::NetworkDevice>& devices) {
   auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->net(),
                                                    ActiveNetworksChanged);
   if (!net_instance)
     return;
 
-  net_instance->ActiveNetworksChanged(TranslateNetworkStates(
-      arc_vpn_service_path_, GetActiveNetworks(), shill_network_properties_));
+  net_instance->ActiveNetworksChanged(
+      TranslateNetworkStates(arc_vpn_service_path_, GetHostActiveNetworks(),
+                             shill_network_properties_, devices));
 }
 
 void ArcNetHostImpl::NetworkListChanged() {
@@ -1108,11 +1165,11 @@
     return !IsActiveNetworkState(
         GetStateHandler()->GetNetworkState(entry.first));
   });
-  const auto active_networks = GetActiveNetworks();
+  const auto active_networks = GetHostActiveNetworks();
   // If there is no active networks, send an explicit ActiveNetworksChanged
   // event to ARC and skip updating Shill properties.
   if (active_networks.empty()) {
-    UpdateActiveNetworks();
+    UpdateActiveNetworks({} /* devices */);
     return;
   }
   for (const auto* network : active_networks)
diff --git a/ash/components/arc/net/arc_net_host_impl.h b/ash/components/arc/net/arc_net_host_impl.h
index 4c222d64..4fafaa7f 100644
--- a/ash/components/arc/net/arc_net_host_impl.h
+++ b/ash/components/arc/net/arc_net_host_impl.h
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "base/values.h"
+#include "chromeos/dbus/patchpanel/patchpanel_service.pb.h"
 #include "chromeos/network/network_connection_observer.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
@@ -118,7 +119,8 @@
 
  private:
   const chromeos::NetworkState* GetDefaultNetworkFromChrome();
-  void UpdateActiveNetworks();
+  void UpdateActiveNetworks(
+      const std::vector<patchpanel::NetworkDevice>& devices);
   void DefaultNetworkSuccessCallback(const std::string& service_path,
                                      const base::DictionaryValue& dictionary);
 
@@ -130,6 +132,11 @@
   // successive Create operations (crbug.com/631646).
   bool GetNetworkPathFromGuid(const std::string& guid, std::string* path);
 
+  // Get active layer 3 network connections for ARC. This function will run
+  // a callback that listed current active networks for ARC.
+  void GetActiveNetworks(GetNetworksCallback callback,
+                         const std::vector<patchpanel::NetworkDevice>& devices);
+
   // Look through the list of known networks for an ARC VPN service.
   // If found, return the Shill service path.  Otherwise return
   // an empty string.  It is assumed that there is at most one ARC VPN
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc
index 60069c71..ac9df12 100644
--- a/ash/system/message_center/ash_notification_view.cc
+++ b/ash/system/message_center/ash_notification_view.cc
@@ -1149,7 +1149,7 @@
   // expanded and collapsed mode if there's a difference between them (a.k.a
   // when `message_label()` is truncated).
   if (message_label() && message_label()->GetVisible() &&
-      message_label()->IsDisplayTextTruncated()) {
+      IsMessageLabelTruncated()) {
     message_center_utils::FadeInView(message_label(),
                                      kMessageLabelFadeInAnimationDelayMs,
                                      kMessageLabelFadeInAnimationDurationMs);
@@ -1158,7 +1158,7 @@
   // Fade in `message_label_in_expanded_state_`.
   if (message_label_in_expanded_state_ &&
       message_label_in_expanded_state_->GetVisible() && message_label() &&
-      message_label()->IsDisplayTextTruncated()) {
+      IsMessageLabelTruncated()) {
     message_center_utils::FadeInView(
         message_label_in_expanded_state_,
         kMessageLabelInExpandedStateFadeInAnimationDelayMs,
@@ -1383,4 +1383,22 @@
          main_view_->bounds().height() - vertical_margin;
 }
 
+bool AshNotificationView::IsMessageLabelTruncated() {
+  // True if the expanded label has more than one line.
+  if (message_label_in_expanded_state_->GetRequiredLines() > 1)
+    return true;
+
+  // Get the first row's width of `message_label_in_expanded_state_`'s text,
+  // which is also the text width of this label since it has one line. If text
+  // width is larger than `left_content()`'s width, which is the space dedicated
+  // to `message_label()`, the text is truncated.
+  int text_width =
+      message_label_in_expanded_state_
+          ->GetSubstringBounds(gfx::Range(
+              0, message_label_in_expanded_state_->GetText().length()))
+          .front()
+          .width();
+  return text_width > left_content()->width();
+}
+
 }  // namespace ash
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h
index fbf0b6b..5fc1dea 100644
--- a/ash/system/message_center/ash_notification_view.h
+++ b/ash/system/message_center/ash_notification_view.h
@@ -209,6 +209,11 @@
   // grouped_notifications_scroll_view_
   int CalculateMaxHeightForGroupedNotifications();
 
+  // Return true is `message_label()` is truncated. We need this helper because
+  // Label::IsDisplayTextTruncated doesn't work when `message_label()` hasn't
+  // been laid out yet.
+  bool IsMessageLabelTruncated();
+
   // Owned by views hierarchy.
   views::View* main_view_ = nullptr;
   views::View* main_right_view_ = nullptr;
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc
index 2f8e582..7a3d995 100644
--- a/base/threading/thread_local_storage_unittest.cc
+++ b/base/threading/thread_local_storage_unittest.cc
@@ -88,9 +88,9 @@
 
 
 void ThreadLocalStorageCleanup(void *value) {
-  int *ptr = reinterpret_cast<int*>(value);
+  int *ptr = static_cast<int*>(value);
   // Destructors should never be called with a NULL.
-  ASSERT_NE(reinterpret_cast<int*>(NULL), ptr);
+  ASSERT_NE(nullptr, ptr);
   if (*ptr == kFinalTlsValue)
     return;  // We've been called enough times.
   ASSERT_LT(kFinalTlsValue, *ptr);
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8a5c7b1..5170f17 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220201.3.1
+7.20220202.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 8a5c7b1..5170f17 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220201.3.1
+7.20220202.1.1
diff --git a/build/toolchain/cros/BUILD.gn b/build/toolchain/cros/BUILD.gn
index 2924c7a..9f6a83e 100644
--- a/build/toolchain/cros/BUILD.gn
+++ b/build/toolchain/cros/BUILD.gn
@@ -7,171 +7,70 @@
 import("//build/toolchain/cros_toolchain.gni")
 import("//build/toolchain/gcc_toolchain.gni")
 
+declare_args() {
+  # If set, build lacros with Chromium's toolchain instead of with Chrome OS's.
+  # TODO(thakis): Set this to `= chromeos_is_browser_only` once that works.
+  lacros_use_chromium_toolchain = false
+}
+
 # This is mostly identical to gcc_toolchain, but handles relativizing toolchain
 # paths. This is needed for CrOS since these paths often change based on the
 # environment. For example, cxx is a relative path picked up on $PATH in the
 # chroot. But in Simple Chrome, cxx is a system-absolute path.
 template("cros_toolchain") {
-  gcc_toolchain(target_name) {
-    forward_variables_from(invoker, "*")
+  if (lacros_use_chromium_toolchain) {
+    clang_toolchain(target_name) {
+      forward_variables_from(invoker, "*")
+    }
+  } else {
+    gcc_toolchain(target_name) {
+      forward_variables_from(invoker, "*")
 
-    # CrOS's target toolchain wrapper prefers to invoke gomacc itself, so pass
-    # it the gomacc path via cmd-line arg. Otherwise, for both CrOS's host
-    # wrapper (used in the ebuild) and Chrome's clang (used in Simple Chrome),
-    # prepend gomacc like normal.
-    if (use_goma && toolchain_args.needs_gomacc_path_arg) {
-      extra_cppflags += " --gomacc-path $goma_dir/gomacc"
-    }
-    if (use_remoteexec && toolchain_args.needs_gomacc_path_arg) {
-      extra_cppflags += "--rewrapper-path $rbe_cros_cc_wrapper --rewrapper-cfg ${rbe_cc_cfg_file}"
-    }
+      toolchain_args.cc_wrapper = ""
+      toolchain_args.clang_use_chrome_plugins = false
 
-    # Relativize path if compiler is specified such that not to lookup from
-    # $PATH and cc/cxx does not contain additional flags.
-    if (cc != get_path_info(cc, "file") && string_replace(cc, " ", "") == cc) {
-      cc = rebase_path(cc, root_build_dir)
-    }
-    if (cxx != get_path_info(cxx, "file") &&
-        string_replace(cxx, " ", "") == cxx) {
-      cxx = rebase_path(cxx, root_build_dir)
-    }
-    if (ar != get_path_info(ar, "file") && string_replace(ar, " ", "") == ar) {
-      ar = rebase_path(ar, root_build_dir)
-    }
-    if (ld != get_path_info(ld, "file") && string_replace(ld, " ", "") == ld) {
-      ld = rebase_path(ld, root_build_dir)
+      # CrOS's target toolchain wrapper prefers to invoke gomacc itself, so pass
+      # it the gomacc path via cmd-line arg. Otherwise, for both CrOS's host
+      # wrapper (used in the ebuild) and Chrome's clang (used in Simple Chrome),
+      # prepend gomacc like normal.
+      if (use_goma && toolchain_args.needs_gomacc_path_arg) {
+        extra_cppflags += " --gomacc-path $goma_dir/gomacc"
+      }
+      if (use_remoteexec && toolchain_args.needs_gomacc_path_arg) {
+        extra_cppflags += "--rewrapper-path $rbe_cros_cc_wrapper --rewrapper-cfg ${rbe_cc_cfg_file}"
+      }
+
+      # Relativize path if compiler is specified such that not to lookup from
+      # $PATH and cc/cxx does not contain additional flags.
+      if (cc != get_path_info(cc, "file") &&
+          string_replace(cc, " ", "") == cc) {
+        cc = rebase_path(cc, root_build_dir)
+      }
+      if (cxx != get_path_info(cxx, "file") &&
+          string_replace(cxx, " ", "") == cxx) {
+        cxx = rebase_path(cxx, root_build_dir)
+      }
+      if (ar != get_path_info(ar, "file") &&
+          string_replace(ar, " ", "") == ar) {
+        ar = rebase_path(ar, root_build_dir)
+      }
+      if (ld != get_path_info(ld, "file") &&
+          string_replace(ld, " ", "") == ld) {
+        ld = rebase_path(ld, root_build_dir)
+      }
     }
   }
 }
 
 # This is the normal toolchain for most targets.
 cros_toolchain("target") {
-  ar = cros_target_ar
-  cc = cros_target_cc
-  cxx = cros_target_cxx
-  ld = cros_target_ld
-
-  if (cros_target_nm != "") {
-    nm = cros_target_nm
-  }
-  if (cros_target_readelf != "") {
-    readelf = cros_target_readelf
-  }
-  extra_cflags = cros_target_extra_cflags
-  extra_cppflags = cros_target_extra_cppflags
-  extra_cxxflags = cros_target_extra_cxxflags
-  extra_ldflags = cros_target_extra_ldflags
-
   toolchain_args = {
-    cc_wrapper = ""
-    needs_gomacc_path_arg = true
-    clang_use_chrome_plugins = false
     current_cpu = target_cpu
     current_os = "chromeos"
     sysroot = target_sysroot
   }
-}
 
-# This is a special toolchain needed just for the nacl_bootstrap target in
-# //native_client/src/trusted/service_runtime/linux. It is identical
-# to ":target" except that it forces use_debug_fission, use_gold, and
-# use_sysroot off, and allows the user to set different sets of extra flags.
-cros_toolchain("nacl_bootstrap") {
-  ar = cros_target_ar
-  cc = cros_target_cc
-  cxx = cros_target_cxx
-  ld = cros_target_ld
-
-  if (cros_target_nm != "") {
-    nm = cros_target_nm
-  }
-  if (cros_target_readelf != "") {
-    readelf = cros_target_readelf
-  }
-  extra_cflags = cros_nacl_bootstrap_extra_cflags
-  extra_cppflags = cros_nacl_bootstrap_extra_cppflags
-  extra_cxxflags = cros_nacl_bootstrap_extra_cxxflags
-  extra_ldflags = cros_nacl_bootstrap_extra_ldflags
-
-  toolchain_args = {
-    cc_wrapper = ""
-    needs_gomacc_path_arg = true
-    clang_use_chrome_plugins = false
-    current_cpu = target_cpu
-    current_os = "chromeos"
-    use_debug_fission = false
-    use_gold = false
-    use_sysroot = false
-  }
-}
-
-cros_toolchain("host") {
-  # These are args for the template.
-  ar = cros_host_ar
-  cc = cros_host_cc
-  cxx = cros_host_cxx
-  ld = cros_host_ld
-
-  if (cros_host_nm != "") {
-    nm = cros_host_nm
-  }
-  if (cros_host_readelf != "") {
-    readelf = cros_host_readelf
-  }
-  extra_cflags = cros_host_extra_cflags
-  extra_cppflags = cros_host_extra_cppflags
-  extra_cxxflags = cros_host_extra_cxxflags
-  extra_ldflags = cros_host_extra_ldflags
-
-  toolchain_args = {
-    cc_wrapper = ""
-    needs_gomacc_path_arg = false
-    clang_use_chrome_plugins = false
-    current_cpu = host_cpu
-    current_os = "linux"
-    sysroot = cros_host_sysroot
-  }
-}
-
-cros_toolchain("v8_snapshot") {
-  # These are args for the template.
-  ar = cros_v8_snapshot_ar
-  cc = cros_v8_snapshot_cc
-  cxx = cros_v8_snapshot_cxx
-  ld = cros_v8_snapshot_ld
-
-  if (cros_v8_snapshot_nm != "") {
-    nm = cros_v8_snapshot_nm
-  }
-  if (cros_v8_snapshot_readelf != "") {
-    readelf = cros_v8_snapshot_readelf
-  }
-  extra_cflags = cros_v8_snapshot_extra_cflags
-  extra_cppflags = cros_v8_snapshot_extra_cppflags
-  extra_cxxflags = cros_v8_snapshot_extra_cxxflags
-  extra_ldflags = cros_v8_snapshot_extra_ldflags
-
-  toolchain_args = {
-    cc_wrapper = ""
-    needs_gomacc_path_arg = false
-    clang_use_chrome_plugins = false
-    if (target_cpu == "x86" || target_cpu == "arm" || target_cpu == "mipsel") {
-      current_cpu = "x86"
-    } else {
-      current_cpu = "x64"
-    }
-    v8_current_cpu = v8_target_cpu
-    current_os = "linux"
-    sysroot = cros_v8_snapshot_sysroot
-  }
-}
-
-# This toolchain is used when we want to build Lacros using alternate toolchain.
-# To use this, you need to set gn arg 'also_build_lacros_chrome_for_architecture'.
-# See build/config/chromeos/ui_mode.gni
-if (also_build_lacros_chrome_for_architecture != "") {
-  cros_toolchain("lacros_clang") {
-    # These are args for the template.
+  if (!lacros_use_chromium_toolchain) {
     ar = cros_target_ar
     cc = cros_target_cc
     cxx = cros_target_cxx
@@ -188,6 +87,112 @@
     extra_cxxflags = cros_target_extra_cxxflags
     extra_ldflags = cros_target_extra_ldflags
 
+    toolchain_args.needs_gomacc_path_arg = true
+  }
+}
+
+# This is a special toolchain needed just for the nacl_bootstrap target in
+# //native_client/src/trusted/service_runtime/linux. It is identical
+# to ":target" except that it forces use_debug_fission, use_gold, and
+# use_sysroot off, and allows the user to set different sets of extra flags.
+cros_toolchain("nacl_bootstrap") {
+  toolchain_args = {
+    current_cpu = target_cpu
+    current_os = "chromeos"
+    use_debug_fission = false
+    use_gold = false
+    use_sysroot = false
+  }
+
+  if (!lacros_use_chromium_toolchain) {
+    ar = cros_target_ar
+    cc = cros_target_cc
+    cxx = cros_target_cxx
+    ld = cros_target_ld
+
+    if (cros_target_nm != "") {
+      nm = cros_target_nm
+    }
+    if (cros_target_readelf != "") {
+      readelf = cros_target_readelf
+    }
+    extra_cflags = cros_nacl_bootstrap_extra_cflags
+    extra_cppflags = cros_nacl_bootstrap_extra_cppflags
+    extra_cxxflags = cros_nacl_bootstrap_extra_cxxflags
+    extra_ldflags = cros_nacl_bootstrap_extra_ldflags
+
+    toolchain_args.needs_gomacc_path_arg = true
+  }
+}
+
+cros_toolchain("host") {
+  toolchain_args = {
+    current_cpu = host_cpu
+    current_os = "linux"
+    sysroot = cros_host_sysroot
+  }
+
+  if (!lacros_use_chromium_toolchain) {
+    # These are args for the template.
+    ar = cros_host_ar
+    cc = cros_host_cc
+    cxx = cros_host_cxx
+    ld = cros_host_ld
+
+    if (cros_host_nm != "") {
+      nm = cros_host_nm
+    }
+    if (cros_host_readelf != "") {
+      readelf = cros_host_readelf
+    }
+    extra_cflags = cros_host_extra_cflags
+    extra_cppflags = cros_host_extra_cppflags
+    extra_cxxflags = cros_host_extra_cxxflags
+    extra_ldflags = cros_host_extra_ldflags
+
+    toolchain_args.needs_gomacc_path_arg = false
+  }
+}
+
+cros_toolchain("v8_snapshot") {
+  toolchain_args = {
+    if (target_cpu == "x86" || target_cpu == "arm" || target_cpu == "mipsel") {
+      current_cpu = "x86"
+    } else {
+      current_cpu = "x64"
+    }
+    v8_current_cpu = v8_target_cpu
+    current_os = "linux"
+    sysroot = cros_v8_snapshot_sysroot
+  }
+
+  if (!lacros_use_chromium_toolchain) {
+    # These are args for the template.
+    ar = cros_v8_snapshot_ar
+    cc = cros_v8_snapshot_cc
+    cxx = cros_v8_snapshot_cxx
+    ld = cros_v8_snapshot_ld
+
+    if (cros_v8_snapshot_nm != "") {
+      nm = cros_v8_snapshot_nm
+    }
+    if (cros_v8_snapshot_readelf != "") {
+      readelf = cros_v8_snapshot_readelf
+    }
+    extra_cflags = cros_v8_snapshot_extra_cflags
+    extra_cppflags = cros_v8_snapshot_extra_cppflags
+    extra_cxxflags = cros_v8_snapshot_extra_cxxflags
+    extra_ldflags = cros_v8_snapshot_extra_ldflags
+
+    toolchain_args.needs_gomacc_path_arg = false
+  }
+}
+
+# This toolchain is used when we want to build Lacros using alternate toolchain.
+# To use this, you need to set gn arg 'also_build_lacros_chrome_for_architecture'.
+# See build/config/chromeos/ui_mode.gni
+if (also_build_lacros_chrome_for_architecture != "") {
+  cros_toolchain("lacros_clang") {
     toolchain_args = {
       if (also_build_lacros_chrome_for_architecture == "amd64") {
         forward_variables_from(
@@ -213,9 +218,26 @@
       chromeos_is_browser_only = true
       use_clang_coverage = false
       cros_host_sysroot = "//build/linux/debian_sid_amd64-sysroot"
-      cc_wrapper = ""
-      needs_gomacc_path_arg = true
-      clang_use_chrome_plugins = false
+    }
+    if (!lacros_use_chromium_toolchain) {
+      # These are args for the template.
+      ar = cros_target_ar
+      cc = cros_target_cc
+      cxx = cros_target_cxx
+      ld = cros_target_ld
+
+      if (cros_target_nm != "") {
+        nm = cros_target_nm
+      }
+      if (cros_target_readelf != "") {
+        readelf = cros_target_readelf
+      }
+      extra_cflags = cros_target_extra_cflags
+      extra_cppflags = cros_target_extra_cppflags
+      extra_cxxflags = cros_target_extra_cxxflags
+      extra_ldflags = cros_target_extra_ldflags
+
+      toolchain_args.needs_gomacc_path_arg = true
     }
   }
 }
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index b2d0b44..9874c7a 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -33,7 +33,12 @@
 }
 
 declare_args() {
-  clang_version = "14.0.0"
+  if (llvm_force_head_revision) {
+    clang_version = "15.0.0"
+  } else {
+    # TODO(crbug.com/1293292): Remove in the next Clang roll.
+    clang_version = "14.0.0"
+  }
 }
 
 # Extension for shared library files (including leading dot).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
index 9b2a9ac..3ecd905 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -46,6 +46,8 @@
 import org.chromium.chrome.browser.password_entry_edit.CredentialEditUiFactory;
 import org.chromium.chrome.browser.password_entry_edit.CredentialEntryFragmentViewBase;
 import org.chromium.chrome.browser.privacy.settings.PrivacySettings;
+import org.chromium.chrome.browser.privacy_sandbox.AdPersonalizationFragment;
+import org.chromium.chrome.browser.privacy_sandbox.AdPersonalizationRemovedFragment;
 import org.chromium.chrome.browser.privacy_sandbox.FlocSettingsFragment;
 import org.chromium.chrome.browser.privacy_sandbox.PrivacySandboxSettingsFragment;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -241,6 +243,12 @@
                                                           .getSiteSettingsDelegate());
             delegate.setSnackbarManager(mSnackbarManager);
         }
+        if (fragment instanceof AdPersonalizationFragment) {
+            ((AdPersonalizationFragment) fragment).setSnackbarManager(getSnackbarManager());
+        }
+        if (fragment instanceof AdPersonalizationRemovedFragment) {
+            ((AdPersonalizationRemovedFragment) fragment).setSnackbarManager(getSnackbarManager());
+        }
     }
 
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
index f79826b9..66f3042f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -399,6 +399,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "https://crbug.com/1291159")
     public void testBatchModeChangesTriggerCorrectSuggestions() {
         final AtomicReference<String> requestedAutocompleteText = new AtomicReference<String>();
         mOmnibox.setText("test");
@@ -415,6 +416,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "https://crbug.com/1291159")
     public void testAutocompleteCorrectlyPerservedOnBatchMode() {
         // Valid case (cursor at the end of text, single character, matches previous autocomplete).
         mOmnibox.setText("g");
@@ -451,6 +453,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "https://crbug.com/1291159")
     public void testAutocompleteSpanClearedOnNonMatchingCommitText() {
         mOmnibox.setText("a");
         mOmnibox.setAutocompleteText("mazon.com");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
index 42e0136..4b1a3367 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.omnibox.suggestions;
 
+import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL;
+import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
+
 import android.app.Activity;
 import android.support.test.InstrumentationRegistry;
 
@@ -24,7 +27,6 @@
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.accessibility.settings.AccessibilitySettings;
-import org.chromium.chrome.browser.app.omnibox.OmniboxPedalDelegateImpl;
 import org.chromium.chrome.browser.autofill.settings.AutofillPaymentMethodsFragment;
 import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTabsFragment;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -32,6 +34,7 @@
 import org.chromium.chrome.browser.omnibox.LocationBarLayout;
 import org.chromium.chrome.browser.omnibox.UrlBar;
 import org.chromium.chrome.browser.omnibox.action.OmniboxPedalType;
+import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionView;
 import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
 import org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment;
 import org.chromium.chrome.browser.settings.MainSettings;
@@ -41,12 +44,13 @@
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ActivityTestUtils;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
+import org.chromium.chrome.test.util.OmniboxTestUtils.SuggestionInfo;
 import org.chromium.chrome.test.util.WaitForFocusHelper;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.site_settings.SiteSettings;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.omnibox.AutocompleteMatch;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.ui.test.util.UiDisableIf;
 
 /**
@@ -59,13 +63,11 @@
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     private OmniboxTestUtils mOmniboxUtils;
-    private OmniboxPedalDelegate mOmniboxPedalDelegate;
 
     @Before
     public void setUp() throws InterruptedException {
         mActivityTestRule.startMainActivityOnBlankPage();
         mOmniboxUtils = new OmniboxTestUtils(mActivityTestRule.getActivity());
-        mOmniboxPedalDelegate = new OmniboxPedalDelegateImpl(mActivityTestRule.getActivity());
     }
 
     /**
@@ -81,7 +83,8 @@
         WaitForFocusHelper.acquireFocusForView(urlBar);
         mOmniboxUtils.requestFocus();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { urlBar.setText(text); });
+        mOmniboxUtils.typeText(text, false);
+        mOmniboxUtils.checkSuggestionsShown();
     }
 
     /**
@@ -95,7 +98,6 @@
     private AutocompleteMatch findOmniboxPedalSuggestion(
             LocationBarLayout locationBarLayout, @OmniboxPedalType int pedalType) {
         ThreadUtils.assertOnUiThread();
-
         AutocompleteCoordinator coordinator = locationBarLayout.getAutocompleteCoordinator();
         // Find the first matching suggestion.
         for (int i = 0; i < coordinator.getSuggestionCount(); ++i) {
@@ -110,11 +112,12 @@
 
     private void clickOnPedal(
             LocationBarLayout locationBarLayout, @OmniboxPedalType int omniboxPedalType) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            AutocompleteMatch matchSuggestion =
-                    findOmniboxPedalSuggestion(locationBarLayout, omniboxPedalType);
-            mOmniboxPedalDelegate.executeAction(matchSuggestion.getOmniboxPedal().getID());
-        });
+        SuggestionInfo<PedalSuggestionView> info =
+                mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION);
+        CriteriaHelper.pollUiThread(() -> {
+            TestTouchUtils.performClickOnMainSync(
+                    InstrumentationRegistry.getInstrumentation(), info.view.getPedalChipView());
+        }, DEFAULT_MAX_TIME_TO_POLL * 5, DEFAULT_POLLING_INTERVAL);
     }
 
     /**
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index ea45954..ccd96c30 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-99.0.4844.16_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-99.0.4844.17_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 48b3995..9359be7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2502,6 +2502,14 @@
      base::size(kQuerySearchBurnInPeriod_500ms), nullptr},
     {"2000ms", kQuerySearchBurnInPeriod_2000ms,
      base::size(kQuerySearchBurnInPeriod_2000ms), nullptr}};
+
+const FeatureEntry::FeatureParam kProductivityLauncher_WithoutContinue[] = {
+    {"enable_continue", "false"}};
+
+const FeatureEntry::FeatureVariation kProductivityLauncherVariations[] = {
+    {"without Continue", kProductivityLauncher_WithoutContinue,
+     base::size(kProductivityLauncher_WithoutContinue), nullptr}};
+
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 constexpr FeatureEntry::FeatureParam kPlatformProvidedTrustTokenIssuance[] = {
@@ -3425,6 +3433,9 @@
          "1",
          autofill::switches::kWalletServiceUseSandbox,
          "0")},
+    {"enable-web-bluetooth", flag_descriptions::kWebBluetoothName,
+     flag_descriptions::kWebBluetoothDescription, kOsLinux,
+     FEATURE_VALUE_TYPE(features::kWebBluetooth)},
     {"enable-web-bluetooth-new-permissions-backend",
      flag_descriptions::kWebBluetoothNewPermissionsBackendName,
      flag_descriptions::kWebBluetoothNewPermissionsBackendDescription,
@@ -3910,7 +3921,24 @@
      flag_descriptions::kCleanUndecryptablePasswordsLinuxDescription, kOsLinux,
      FEATURE_VALUE_TYPE(
          password_manager::features::kSyncUndecryptablePasswordsLinux)},
-#endif
+
+    {"force-password-initial-sync-when-decryption-fails",
+     flag_descriptions::kForcePasswordInitialSyncWhenDecryptionFailsName,
+     flag_descriptions::kForcePasswordInitialSyncWhenDecryptionFailsDescription,
+     kOsLinux,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kForceInitialSyncWhenDecryptionFails)},
+#endif  // BUILDFLAG(IS_LINUX)
+
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+    {"skip-undecryptable-passwords",
+     flag_descriptions::kSkipUndecryptablePasswordsName,
+     flag_descriptions::kSkipUndecryptablePasswordsDescription,
+     kOsLinux | kOsMac,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kSkipUndecryptablePasswords)},
+
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
 
 #if BUILDFLAG(ENABLE_VR)
     {"webxr-incubations", flag_descriptions::kWebXrIncubationsName,
@@ -6613,7 +6641,9 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     {"productivity-launcher", flag_descriptions::kProductivityLauncherName,
      flag_descriptions::kProductivityLauncherDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kProductivityLauncher)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(ash::features::kProductivityLauncher,
+                                    kProductivityLauncherVariations,
+                                    "ProductivityLauncher")},
     {"shelf-drag-to-pin", flag_descriptions::kShelfDragToPinName,
      flag_descriptions::kShelfDragToPinDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kDragUnpinnedAppToPin)},
diff --git a/chrome/browser/android/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc
index 94fb95b..e9504034 100644
--- a/chrome/browser/android/autofill_assistant/client_android.cc
+++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -69,11 +69,8 @@
     const JavaParamRef<jobject>& jweb_contents,
     const JavaParamRef<jobject>& jdependencies) {
   auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
-  std::unique_ptr<Dependencies> dependencies =
-      Dependencies::CreateFromJavaDependencies(
-          ScopedJavaGlobalRef<jobject>(jdependencies));
-
-  ClientAndroid::CreateForWebContents(web_contents, std::move(dependencies));
+  ClientAndroid::CreateForWebContents(
+      web_contents, ScopedJavaGlobalRef<jobject>(jdependencies));
   return ClientAndroid::FromWebContents(web_contents)->GetJavaObject();
 }
 
@@ -101,13 +98,14 @@
 }
 
 ClientAndroid::ClientAndroid(content::WebContents* web_contents,
-                             std::unique_ptr<Dependencies> dependencies)
+                             const ScopedJavaGlobalRef<jobject>& jdependencies)
     : content::WebContentsUserData<ClientAndroid>(*web_contents),
+      dependencies_(Dependencies::CreateFromJavaDependencies(jdependencies)),
+      jdependencies_(jdependencies),
       java_object_(Java_AutofillAssistantClient_Constructor(
           AttachCurrentThread(),
           reinterpret_cast<intptr_t>(this),
-          dependencies->CreateAccessTokenUtil())),
-      dependencies_(std::move(dependencies)) {}
+          dependencies_->CreateAccessTokenUtil())) {}
 
 ClientAndroid::~ClientAndroid() {
   if (controller_ != nullptr && started_) {
@@ -422,7 +420,7 @@
 base::android::ScopedJavaGlobalRef<jobject> ClientAndroid::GetDependencies(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller) {
-  return dependencies_->GetJavaDependencies();
+  return jdependencies_;
 }
 
 int ClientAndroid::FindDirectAction(const std::string& action_name) {
@@ -451,8 +449,7 @@
     const base::android::JavaRef<jobject>& joverlay_coordinator) {
   if (!ui_controller_android_) {
     ui_controller_android_ = UiControllerAndroid::CreateFromWebContents(
-        GetWebContents(), dependencies_->GetJavaDependencies(),
-        joverlay_coordinator);
+        GetWebContents(), jdependencies_, joverlay_coordinator);
     if (!ui_controller_android_) {
       // The activity is not or not yet in a mode where attaching the UI is
       // possible.
@@ -581,7 +578,7 @@
 
 bool ClientAndroid::IsAccessibilityEnabled() const {
   return Java_AutofillAssistantClient_isAccessibilityEnabled(
-      AttachCurrentThread(), dependencies_->GetJavaDependencies());
+      AttachCurrentThread(), jdependencies_);
 }
 
 bool ClientAndroid::IsSpokenFeedbackAccessibilityServiceEnabled() const {
diff --git a/chrome/browser/android/autofill_assistant/client_android.h b/chrome/browser/android/autofill_assistant/client_android.h
index 0856cbd..71082bceb4 100644
--- a/chrome/browser/android/autofill_assistant/client_android.h
+++ b/chrome/browser/android/autofill_assistant/client_android.h
@@ -156,8 +156,9 @@
  private:
   friend class content::WebContentsUserData<ClientAndroid>;
 
-  explicit ClientAndroid(content::WebContents* web_contents,
-                         std::unique_ptr<Dependencies> dependencies);
+  explicit ClientAndroid(
+      content::WebContents* web_contents,
+      const base::android::ScopedJavaGlobalRef<jobject>& jdependencies);
 
   void CreateController(
       std::unique_ptr<Service> service,
@@ -181,13 +182,14 @@
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 
+  const std::unique_ptr<const Dependencies> dependencies_;
+  const base::android::ScopedJavaGlobalRef<jobject> jdependencies_;
+
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
   std::unique_ptr<Controller> controller_;
   std::unique_ptr<UiController> ui_controller_;
   mutable std::unique_ptr<WebsiteLoginManager> website_login_manager_;
 
-  const std::unique_ptr<Dependencies> dependencies_;
-
   // True if Start() was called. This turns on the tracking of dropouts.
   bool started_ = false;
 
diff --git a/chrome/browser/android/autofill_assistant/dependencies.cc b/chrome/browser/android/autofill_assistant/dependencies.cc
index 4f0d3eb..94382140 100644
--- a/chrome/browser/android/autofill_assistant/dependencies.cc
+++ b/chrome/browser/android/autofill_assistant/dependencies.cc
@@ -8,51 +8,43 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_piece.h"
+#include "chrome/android/features/autofill_assistant/jni_headers_public/AssistantDependencies_jni.h"
 #include "chrome/android/features/autofill_assistant/jni_headers_public/AssistantStaticDependencies_jni.h"
 
 using ::base::android::AttachCurrentThread;
 using ::base::android::JavaParamRef;
+using ::base::android::JavaRef;
 using ::base::android::ScopedJavaGlobalRef;
 
 namespace autofill_assistant {
 
-std::unique_ptr<Dependencies> Dependencies::CreateFromJavaDependencies(
-    ScopedJavaGlobalRef<jobject> jdependencies) {
-  std::unique_ptr<Dependencies> dependencies =
-      CreateFromJavaStaticDependencies(jdependencies);
-  dependencies->SetJavaDependencies(jdependencies);
-  return dependencies;
-}
-
 std::unique_ptr<Dependencies> Dependencies::CreateFromJavaStaticDependencies(
-    ScopedJavaGlobalRef<jobject> jstatic_dependencies) {
+    const JavaRef<jobject>& jstatic_dependencies) {
   return base::WrapUnique(reinterpret_cast<Dependencies*>(
       Java_AssistantStaticDependencies_createNative(AttachCurrentThread(),
                                                     jstatic_dependencies)));
 }
 
+std::unique_ptr<Dependencies> Dependencies::CreateFromJavaDependencies(
+    const JavaRef<jobject>& jdependencies) {
+  const auto jstatic_dependencies =
+      Java_AssistantDependencies_getStaticDependencies(AttachCurrentThread(),
+                                                       jdependencies);
+  return CreateFromJavaStaticDependencies(jstatic_dependencies);
+}
+
 Dependencies::Dependencies(JNIEnv* env,
                            const JavaParamRef<jobject>& jstatic_dependencies)
     : jstatic_dependencies_(jstatic_dependencies) {}
 
-void Dependencies::SetJavaDependencies(
-    base::android::ScopedJavaGlobalRef<jobject> jdependencies) {
-  jdependencies_ = jdependencies;
-}
-
 ScopedJavaGlobalRef<jobject> Dependencies::GetJavaStaticDependencies() const {
   return jstatic_dependencies_;
 }
 
-ScopedJavaGlobalRef<jobject> Dependencies::GetJavaDependencies() const {
-  return jdependencies_;
-}
-
-ScopedJavaGlobalRef<jobject> Dependencies::CreateInfoPageUtil(
-    const ScopedJavaGlobalRef<jobject>& jstatic_dependencies) {
+ScopedJavaGlobalRef<jobject> Dependencies::CreateInfoPageUtil() const {
   return ScopedJavaGlobalRef<jobject>(
       Java_AssistantStaticDependencies_createInfoPageUtil(
-          AttachCurrentThread(), jstatic_dependencies));
+          AttachCurrentThread(), jstatic_dependencies_));
 }
 
 ScopedJavaGlobalRef<jobject> Dependencies::CreateAccessTokenUtil() const {
diff --git a/chrome/browser/android/autofill_assistant/dependencies.h b/chrome/browser/android/autofill_assistant/dependencies.h
index f300e1e..ba67fcc 100644
--- a/chrome/browser/android/autofill_assistant/dependencies.h
+++ b/chrome/browser/android/autofill_assistant/dependencies.h
@@ -20,21 +20,14 @@
 // and dependencies to the starter.
 class Dependencies {
  public:
-  static std::unique_ptr<Dependencies> CreateFromJavaDependencies(
-      base::android::ScopedJavaGlobalRef<jobject> jdependencies);
-
   static std::unique_ptr<Dependencies> CreateFromJavaStaticDependencies(
-      base::android::ScopedJavaGlobalRef<jobject> jstatic_dependencies);
+      const base::android::JavaRef<jobject>& jstatic_dependencies);
+
+  static std::unique_ptr<Dependencies> CreateFromJavaDependencies(
+      const base::android::JavaRef<jobject>& jdependencies);
 
   base::android::ScopedJavaGlobalRef<jobject> GetJavaStaticDependencies() const;
-  // Might not be null during initiation in starter_android.
-  base::android::ScopedJavaGlobalRef<jobject> GetJavaDependencies() const;
-
-  void SetJavaDependencies(base::android::ScopedJavaGlobalRef<jobject>);
-
-  static base::android::ScopedJavaGlobalRef<jobject> CreateInfoPageUtil(
-      const base::android::ScopedJavaGlobalRef<jobject>& jstatic_dependencies);
-
+  base::android::ScopedJavaGlobalRef<jobject> CreateInfoPageUtil() const;
   base::android::ScopedJavaGlobalRef<jobject> CreateAccessTokenUtil() const;
 
   virtual ~Dependencies();
@@ -57,8 +50,6 @@
 
  private:
   const base::android::ScopedJavaGlobalRef<jobject> jstatic_dependencies_;
-  // Might be null during initiation in starter_android.
-  base::android::ScopedJavaGlobalRef<jobject> jdependencies_;
 };
 
 }  // namespace autofill_assistant
diff --git a/chrome/browser/android/autofill_assistant/starter_android.cc b/chrome/browser/android/autofill_assistant/starter_android.cc
index bcc8dff..686e06d7 100644
--- a/chrome/browser/android/autofill_assistant/starter_android.cc
+++ b/chrome/browser/android/autofill_assistant/starter_android.cc
@@ -61,7 +61,7 @@
 
 void StarterAndroid::Detach(JNIEnv* env, const JavaParamRef<jobject>& jcaller) {
   java_object_ = nullptr;
-  dependencies_ = nullptr;
+  java_dependencies_ = nullptr;
   starter_.reset();
 }
 
@@ -70,8 +70,7 @@
   CreateJavaDependenciesIfNecessary();
   return std::make_unique<TriggerScriptBridgeAndroid>(
       base::android::AttachCurrentThread(),
-      GetWebContents().GetJavaWebContents(),
-      dependencies_->GetJavaDependencies());
+      GetWebContents().GetJavaWebContents(), java_dependencies_);
 }
 
 std::unique_ptr<ServiceRequestSender>
@@ -127,7 +126,7 @@
 void StarterAndroid::OnActivityAttachmentChanged(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller) {
-  dependencies_ = nullptr;
+  java_dependencies_ = nullptr;
   if (!starter_) {
     return;
   }
@@ -184,7 +183,7 @@
 }
 
 void StarterAndroid::HideOnboarding() {
-  if (!dependencies_) {
+  if (!java_dependencies_) {
     return;
   }
   Java_Starter_hideOnboarding(base::android::AttachCurrentThread(),
@@ -244,7 +243,7 @@
 }
 
 void StarterAndroid::CreateJavaDependenciesIfNecessary() {
-  if (dependencies_) {
+  if (java_dependencies_) {
     return;
   }
 
@@ -257,12 +256,7 @@
     return;
   }
 
-  ScopedJavaGlobalRef<jobject> jdependencies =
-      ScopedJavaGlobalRef<jobject>(*array.begin());
-  if (!jdependencies.is_null()) {
-    dependencies_ = Dependencies::CreateFromJavaDependencies(jdependencies);
-  }
-
+  java_dependencies_ = *array.begin();
   java_onboarding_helper_ = *(++array.begin());
 }
 
@@ -291,8 +285,7 @@
     std::unique_ptr<TriggerContext> trigger_context,
     const absl::optional<TriggerScriptProto>& trigger_script) {
   CreateJavaDependenciesIfNecessary();
-  ClientAndroid::CreateForWebContents(&GetWebContents(),
-                                      std::move(dependencies_));
+  ClientAndroid::CreateForWebContents(&GetWebContents(), java_dependencies_);
   auto* client_android = ClientAndroid::FromWebContents(&GetWebContents());
   DCHECK(client_android);
 
diff --git a/chrome/browser/android/autofill_assistant/starter_android.h b/chrome/browser/android/autofill_assistant/starter_android.h
index c8feb28..8e1ea56 100644
--- a/chrome/browser/android/autofill_assistant/starter_android.h
+++ b/chrome/browser/android/autofill_assistant/starter_android.h
@@ -121,9 +121,9 @@
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
   std::unique_ptr<Starter> starter_;
-  std::unique_ptr<Dependencies> dependencies_;
 
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
+  base::android::ScopedJavaGlobalRef<jobject> java_dependencies_;
   base::android::ScopedJavaGlobalRef<jobject> java_onboarding_helper_;
   std::unique_ptr<WebsiteLoginManager> website_login_manager_;
   base::OnceCallback<void(Metrics::FeatureModuleInstallation result)>
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index f79a7a5..18bbdf31 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -29,7 +29,6 @@
 #include "chrome/android/features/autofill_assistant/jni_headers/AssistantOverlayModel_jni.h"
 #include "chrome/android/features/autofill_assistant/jni_headers/AssistantPlaceholdersConfiguration_jni.h"
 #include "chrome/android/features/autofill_assistant/jni_headers/AutofillAssistantUiController_jni.h"
-#include "chrome/android/features/autofill_assistant/jni_headers_public/AssistantDependencies_jni.h"
 #include "chrome/browser/android/autofill_assistant/client_android.h"
 #include "chrome/browser/android/autofill_assistant/dependencies.h"
 #include "chrome/browser/android/autofill_assistant/generic_ui_root_controller_android.h"
@@ -277,9 +276,7 @@
       form_delegate_(this),
       generic_ui_delegate_(this),
       bottom_bar_delegate_(this),
-      jstatic_dependencies_(
-          Java_AssistantDependencies_getStaticDependencies(env,
-                                                           jdependencies)) {
+      dependencies_(Dependencies::CreateFromJavaDependencies(jdependencies)) {
   java_object_ = Java_AutofillAssistantUiController_Constructor(
       env, reinterpret_cast<intptr_t>(this), jdependencies,
       /* allowTabSwitching= */
@@ -1172,7 +1169,7 @@
 }
 
 ScopedJavaGlobalRef<jobject> UiControllerAndroid::GetInfoPageUtil() const {
-  return Dependencies::CreateInfoPageUtil(jstatic_dependencies_);
+  return dependencies_->CreateInfoPageUtil();
 }
 
 void UiControllerAndroid::OnCollectUserDataOptionsChanged(
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h
index 920241cc..2ba91bf6 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.h
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/android/autofill_assistant/assistant_header_delegate.h"
 #include "chrome/browser/android/autofill_assistant/assistant_header_model.h"
 #include "chrome/browser/android/autofill_assistant/assistant_overlay_delegate.h"
+#include "chrome/browser/android/autofill_assistant/dependencies.h"
 #include "components/autofill_assistant/browser/chip.h"
 #include "components/autofill_assistant/browser/controller_observer.h"
 #include "components/autofill_assistant/browser/details.h"
@@ -301,7 +302,7 @@
 
   // Java-side AssistantStaticDependencies object. This never changes during the
   // life of the application.
-  const base::android::ScopedJavaGlobalRef<jobject> jstatic_dependencies_;
+  const std::unique_ptr<const Dependencies> dependencies_;
 
   // Native controllers for generic UI.
   std::unique_ptr<GenericUiRootControllerAndroid>
diff --git a/chrome/browser/android/omnibox/omnibox_prerender.cc b/chrome/browser/android/omnibox/omnibox_prerender.cc
index 0b5ad20..6900087 100644
--- a/chrome/browser/android/omnibox/omnibox_prerender.cc
+++ b/chrome/browser/android/omnibox/omnibox_prerender.cc
@@ -156,9 +156,7 @@
     DCHECK(prerender_utils::IsSearchSuggestionPrerenderEnabled());
     PrerenderManager::CreateForWebContents(web_contents);
     auto* prerender_manager = PrerenderManager::FromWebContents(web_contents);
-    prerender_manager->Start(
-        match.destination_url,
-        PrerenderManager::TriggerReason::kSearchSuggestion);
+    prerender_manager->StartPrerenderAutocompleteMatch(match);
   } else {
     gfx::Rect container_bounds = web_contents->GetContainerBounds();
     predictors::AutocompleteActionPredictorFactory::GetForProfile(profile)
diff --git a/chrome/browser/ash/arc/arc_util.cc b/chrome/browser/ash/arc/arc_util.cc
index 06a0010..c1c7fd4 100644
--- a/chrome/browser/ash/arc/arc_util.cc
+++ b/chrome/browser/ash/arc/arc_util.cc
@@ -107,10 +107,10 @@
 
 FileSystemCompatibilityState GetFileSystemCompatibilityPref(
     const AccountId& account_id) {
-  int pref_value = kFileSystemIncompatible;
-  user_manager::known_user::GetIntegerPref(
-      account_id, prefs::kArcCompatibleFilesystemChosen, &pref_value);
-  return static_cast<FileSystemCompatibilityState>(pref_value);
+  user_manager::KnownUser known_user(g_browser_process->local_state());
+  return static_cast<FileSystemCompatibilityState>(
+      known_user.FindIntPath(account_id, prefs::kArcCompatibleFilesystemChosen)
+          .value_or(kFileSystemIncompatible));
 }
 
 // Stores the result of IsArcCompatibleFilesystem posted back from the blocking
@@ -119,9 +119,9 @@
                                    base::OnceClosure callback,
                                    bool is_compatible) {
   if (is_compatible) {
-    user_manager::known_user::SetIntegerPref(
-        account_id, prefs::kArcCompatibleFilesystemChosen,
-        kFileSystemCompatible);
+    user_manager::KnownUser known_user(g_browser_process->local_state());
+    known_user.SetIntegerPref(account_id, prefs::kArcCompatibleFilesystemChosen,
+                              kFileSystemCompatible);
 
     // TODO(kinaba): Remove this code for accounts without user prefs.
     // See the comment for |g_known_compatible_users| for the detail.
diff --git a/chrome/browser/ash/arc/arc_util_unittest.cc b/chrome/browser/ash/arc/arc_util_unittest.cc
index 0781a14..96fa0a8 100644
--- a/chrome/browser/ash/arc/arc_util_unittest.cc
+++ b/chrome/browser/ash/arc/arc_util_unittest.cc
@@ -398,20 +398,20 @@
   // Unconfirmed
   EXPECT_FALSE(IsArcCompatibleFileSystemUsedForUser(user));
 
+  user_manager::KnownUser known_user(g_browser_process->local_state());
   // Old FS
-  user_manager::known_user::SetIntegerPref(
-      id, prefs::kArcCompatibleFilesystemChosen, kFileSystemIncompatible);
+  known_user.SetIntegerPref(id, prefs::kArcCompatibleFilesystemChosen,
+                            kFileSystemIncompatible);
   EXPECT_FALSE(IsArcCompatibleFileSystemUsedForUser(user));
 
   // New FS
-  user_manager::known_user::SetIntegerPref(
-      id, prefs::kArcCompatibleFilesystemChosen, kFileSystemCompatible);
+  known_user.SetIntegerPref(id, prefs::kArcCompatibleFilesystemChosen,
+                            kFileSystemCompatible);
   EXPECT_TRUE(IsArcCompatibleFileSystemUsedForUser(user));
 
   // New FS (User notified)
-  user_manager::known_user::SetIntegerPref(
-      id, prefs::kArcCompatibleFilesystemChosen,
-      kFileSystemCompatibleAndNotifiedDeprecated);
+  known_user.SetIntegerPref(id, prefs::kArcCompatibleFilesystemChosen,
+                            kFileSystemCompatibleAndNotifiedDeprecated);
   EXPECT_TRUE(IsArcCompatibleFileSystemUsedForUser(user));
 }
 
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc
index e765818..6377e12 100644
--- a/chrome/browser/ash/crosapi/browser_manager.cc
+++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -478,6 +478,23 @@
   browser_service_->service->NewFullscreenWindow(url, std::move(callback));
 }
 
+void BrowserManager::NewGuestWindow() {
+  auto result = MaybeStart(browser_util::InitialBrowserAction(
+      mojom::InitialBrowserAction::kOpenGuestWindow));
+  if (result != MaybeStartResult::kRunning)
+    return;
+
+  if (!browser_service_.has_value()) {
+    LOG(ERROR) << "BrowserService was disconnected";
+    return;
+  }
+
+  if (!NewFullscreenWindowSupported())
+    return;
+
+  browser_service_->service->NewGuestWindow(base::DoNothing());
+}
+
 void BrowserManager::NewTab() {
   auto result = MaybeStart(browser_util::InitialBrowserAction(
       mojom::InitialBrowserAction::kOpenNewTabPageWindow));
@@ -1292,4 +1309,10 @@
   browser_service_->service->OpenUrl(url, std::move(params), base::DoNothing());
 }
 
+bool BrowserManager::IsNewGuestWindowSupported() const {
+  return browser_service_.has_value() &&
+         browser_service_->interface_version >=
+             crosapi::mojom::BrowserService::kNewGuestWindowMinVersion;
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/browser_manager.h b/chrome/browser/ash/crosapi/browser_manager.h
index 752d9e5..c0dddff8 100644
--- a/chrome/browser/ash/crosapi/browser_manager.h
+++ b/chrome/browser/ash/crosapi/browser_manager.h
@@ -133,6 +133,10 @@
   virtual void NewFullscreenWindow(const GURL& url,
                                    NewFullscreenWindowCallback callback);
 
+  // Opens a new window in lacros-chrome with the Guest profile if the Guest
+  // mode is enabled.
+  void NewGuestWindow();
+
   // Similar to NewWindow(), but opens a tab, instead.
   // See crosapi::mojom::BrowserService::NewTab for more details
   void NewTab();
@@ -410,6 +414,11 @@
       const GURL& url,
       crosapi::mojom::OpenUrlParams::WindowOpenDisposition disposition);
 
+  // Returns true if the crosapi interface of the currently running lacros
+  // supports NewGuestWindow API. If lacros is older or lacros is not running,
+  // this returns false.
+  bool IsNewGuestWindowSupported() const;
+
   State state_ = State::NOT_INITIALIZED;
 
   std::unique_ptr<crosapi::BrowserLoader> browser_loader_;
diff --git a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
index 3c0711d..39e7769 100644
--- a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
+++ b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
@@ -76,6 +76,7 @@
       NewWindowForDetachingTabCallback closure) override {}
   void NewFullscreenWindow(const GURL& url,
                            NewFullscreenWindowCallback callback) override {}
+  void NewGuestWindow(NewGuestWindowCallback callback) override {}
   void NewTab(NewTabCallback callback) override {}
   void OpenUrl(const GURL& url,
                crosapi::mojom::OpenUrlParamsPtr params,
diff --git a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
index 0a4bc19b..3dbc994 100644
--- a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
+++ b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
@@ -486,6 +486,10 @@
   FRERequirement fre_requirement = GetFRERequirement();
   LOG_DETERMINATION() << FRERequirementToString(fre_requirement);
 
+  // Skip FRE check if the device is explicitly marked as consumer owned.
+  if (fre_requirement == FRERequirement::kExplicitlyNotRequired)
+    return AutoEnrollmentCheckType::kNone;
+
   if (ShouldDoFRECheck(command_line, fre_requirement)) {
     // FRE has precedence over Initial Enrollment.
     LOG(WARNING) << "Proceeding with FRE check.";
diff --git a/chrome/browser/ash/login/lock_screen_utils.cc b/chrome/browser/ash/login/lock_screen_utils.cc
index f210719..e96de31 100644
--- a/chrome/browser/ash/login/lock_screen_utils.cc
+++ b/chrome/browser/ash/login/lock_screen_utils.cc
@@ -163,15 +163,16 @@
     }
   }
 
-  int auto_repeat_delay = kDefaultKeyAutoRepeatDelay.InMilliseconds();
-  int auto_repeat_interval = kDefaultKeyAutoRepeatInterval.InMilliseconds();
-  user_manager::known_user::GetIntegerPref(
-      account_id, prefs::kXkbAutoRepeatDelay, &auto_repeat_delay);
-  user_manager::known_user::GetIntegerPref(
-      account_id, prefs::kXkbAutoRepeatInterval, &auto_repeat_interval);
   input_method::AutoRepeatRate rate;
-  rate.initial_delay_in_ms = auto_repeat_delay;
-  rate.repeat_interval_in_ms = auto_repeat_interval;
+
+  rate.initial_delay_in_ms =
+      known_user.FindIntPath(account_id, prefs::kXkbAutoRepeatDelay)
+          .value_or(kDefaultKeyAutoRepeatDelay.InMilliseconds());
+
+  rate.repeat_interval_in_ms =
+      known_user.FindIntPath(account_id, prefs::kXkbAutoRepeatInterval)
+          .value_or(kDefaultKeyAutoRepeatInterval.InMilliseconds());
+
   input_method::InputMethodManager::Get()
       ->GetImeKeyboard()
       ->SetAutoRepeatEnabled(true);
diff --git a/chrome/browser/ash/login/reauth_stats.cc b/chrome/browser/ash/login/reauth_stats.cc
index 6523081..458ff2fa 100644
--- a/chrome/browser/ash/login/reauth_stats.cc
+++ b/chrome/browser/ash/login/reauth_stats.cc
@@ -6,41 +6,40 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
+#include "chrome/browser/browser_process.h"
 #include "components/user_manager/known_user.h"
 
 namespace ash {
 
 void RecordReauthReason(const AccountId& account_id, ReauthReason reason) {
-  int old_reason;
+  if (reason == ReauthReason::NONE)
+    return;
+  user_manager::KnownUser known_user(g_browser_process->local_state());
   // We record only the first value, skipping everything else, except "none"
   // value, which is used to reset the current state.
-  if (!user_manager::known_user::FindReauthReason(account_id, &old_reason) ||
-      (static_cast<ReauthReason>(old_reason) == ReauthReason::NONE &&
-       reason != ReauthReason::NONE)) {
-    LOG(WARNING) << "Reauth reason updated: " << reason;
-    user_manager::known_user::UpdateReauthReason(account_id,
-                                                 static_cast<int>(reason));
+  if (known_user.FindReauthReason(account_id).value_or(ReauthReason::NONE) ==
+      reason) {
+    return;
   }
+  LOG(WARNING) << "Reauth reason updated: " << reason;
+  known_user.UpdateReauthReason(account_id, static_cast<int>(reason));
 }
 
 void SendReauthReason(const AccountId& account_id, bool password_changed) {
-  int reauth_reason_int;
-  if (!user_manager::known_user::FindReauthReason(account_id,
-                                                  &reauth_reason_int)) {
+  user_manager::KnownUser known_user(g_browser_process->local_state());
+  ReauthReason reauth_reason = static_cast<ReauthReason>(
+      known_user.FindReauthReason(account_id).value_or(ReauthReason::NONE));
+  if (reauth_reason == ReauthReason::NONE)
     return;
+  if (password_changed) {
+    base::UmaHistogramEnumeration("Login.PasswordChanged.ReauthReason",
+                                  reauth_reason, NUM_REAUTH_FLOW_REASONS);
+  } else {
+    base::UmaHistogramEnumeration("Login.PasswordNotChanged.ReauthReason",
+                                  reauth_reason, NUM_REAUTH_FLOW_REASONS);
   }
-  ReauthReason reauth_reason = static_cast<ReauthReason>(reauth_reason_int);
-  if (reauth_reason != ReauthReason::NONE) {
-    if (password_changed) {
-      base::UmaHistogramEnumeration("Login.PasswordChanged.ReauthReason",
-                                    reauth_reason, NUM_REAUTH_FLOW_REASONS);
-    } else {
-      base::UmaHistogramEnumeration("Login.PasswordNotChanged.ReauthReason",
-                                    reauth_reason, NUM_REAUTH_FLOW_REASONS);
-    }
-    user_manager::known_user::UpdateReauthReason(
-        account_id, static_cast<int>(ReauthReason::NONE));
-  }
+  known_user.UpdateReauthReason(account_id,
+                                static_cast<int>(ReauthReason::NONE));
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/signin/offline_signin_limiter_unittest.cc b/chrome/browser/ash/login/signin/offline_signin_limiter_unittest.cc
index 84a63e8..c5603ba 100644
--- a/chrome/browser/ash/login/signin/offline_signin_limiter_unittest.cc
+++ b/chrome/browser/ash/login/signin/offline_signin_limiter_unittest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ash/login/signin/offline_signin_limiter_factory.h"
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -57,7 +58,6 @@
   void DestroyLimiter();
   void CreateLimiter();
 
-  void SetUpUserManager();
   void AddGaiaUser();
   void AddSAMLUser();
 
@@ -66,8 +66,6 @@
   const AccountId test_saml_account_id_ =
       AccountId::FromUserEmail(kTestSAMLUser);
 
-  TestingPrefServiceSimple* GetTestingLocalState();
-
   content::BrowserTaskEnvironment task_environment_;
   extensions::QuotaService::ScopedDisablePurgeForTesting
       disable_purge_for_testing_;
@@ -76,23 +74,23 @@
   user_manager::ScopedUserManager user_manager_enabler_;
 
   std::unique_ptr<TestingProfile> profile_;
-  base::WallClockTimer* timer_;  // Not owned.
+  base::WallClockTimer* timer_ = nullptr;  // Not owned.
 
-  OfflineSigninLimiter* limiter_;  // Owned.
+  OfflineSigninLimiter* limiter_ = nullptr;  // Owned.
   base::test::ScopedPowerMonitorTestSource test_power_monitor_source_;
 
-  TestingPrefServiceSimple testing_local_state_;
+  std::unique_ptr<ScopedTestingLocalState> local_state_;
   base::test::ScopedFeatureList feature_list_;
 };
 
 OfflineSigninLimiterTest::OfflineSigninLimiterTest()
     : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
       user_manager_(new MockUserManager),
-      user_manager_enabler_(base::WrapUnique(user_manager_)),
-      timer_(nullptr),
-      limiter_(nullptr) {
+      user_manager_enabler_(base::WrapUnique(user_manager_)) {
   feature_list_.InitAndEnableFeature(
       features::kEnableSamlReauthenticationOnLockscreen);
+  local_state_ = std::make_unique<ScopedTestingLocalState>(
+      TestingBrowserProcess::GetGlobal());
 }
 
 OfflineSigninLimiterTest::~OfflineSigninLimiterTest() {
@@ -103,6 +101,7 @@
   profile_ = nullptr;
   // Finish any pending tasks before deleting the TestingBrowserProcess.
   task_environment_.RunUntilIdle();
+  local_state_.reset();
   TestingBrowserProcess::DeleteInstance();
 }
 
@@ -122,11 +121,6 @@
   timer_ = limiter_->GetTimerForTesting();
 }
 
-void OfflineSigninLimiterTest::SetUpUserManager() {
-  EXPECT_CALL(*user_manager_, GetLocalState())
-      .WillRepeatedly(Return(GetTestingLocalState()));
-}
-
 void OfflineSigninLimiterTest::SetUp() {
   profile_ = std::make_unique<TestingProfile>();
 }
@@ -134,21 +128,11 @@
 void OfflineSigninLimiterTest::AddGaiaUser() {
   user_manager_->AddUser(test_gaia_account_id_);
   profile_->set_profile_name(kTestGaiaUser);
-
-  user_manager_->RegisterPrefs(GetTestingLocalState()->registry());
-  SetUpUserManager();
 }
 
 void OfflineSigninLimiterTest::AddSAMLUser() {
   user_manager_->AddPublicAccountWithSAML(test_saml_account_id_);
   profile_->set_profile_name(kTestSAMLUser);
-
-  user_manager_->RegisterPrefs(GetTestingLocalState()->registry());
-  SetUpUserManager();
-}
-
-TestingPrefServiceSimple* OfflineSigninLimiterTest::GetTestingLocalState() {
-  return &testing_local_state_;
 }
 
 TEST_F(OfflineSigninLimiterTest, NoGaiaDefaultLimit) {
@@ -158,7 +142,6 @@
   // Authenticate offline. Verify that the flag enforcing online login is not
   // changed and the time of last login with SAML is not set.
   CreateLimiter();
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -182,7 +165,6 @@
   // Authenticate offline. Verify that the flag enforcing online login is not
   // changed and the time of last login with SAML is not set.
   CreateLimiter();
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -237,7 +219,6 @@
   // Authenticate offline. Verify that the flag enforcing online login is not
   // changed.
   CreateLimiter();
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_saml_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -321,7 +302,6 @@
   // online login is cleared and the time of last login without SAML is updated.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_gaia_account_id_, false))
       .Times(1);
@@ -347,7 +327,6 @@
   // time of last login without SAML are not changed.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -394,7 +373,6 @@
   // online login is cleared and the time of last login without SAML is updated.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_gaia_account_id_, false))
       .Times(1);
@@ -420,7 +398,6 @@
   // time of last login without SAML are not changed.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -486,7 +463,6 @@
 
   // Set a zero time limit. Verify that the flag enforcing online login is set.
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_gaia_account_id_, false))
       .Times(0);
@@ -528,7 +504,6 @@
 
   // Verify that the flag enforcing online login is not changed.
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
 }
@@ -693,7 +668,6 @@
   // online login is cleared and the time of last login without SAML is set.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_gaia_account_id_, false))
       .Times(1);
@@ -719,7 +693,6 @@
   // time of last login without SAML are not changed.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -764,7 +737,6 @@
   // changed and the time of last login with SAML is not set.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -814,7 +786,6 @@
   // changed and the time of last login with SAML is not set.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -864,7 +835,6 @@
   // changed and the time of last login with SAML is not set.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_gaia_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -1011,7 +981,6 @@
   // login is cleared and the time of last login with SAML is updated.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_saml_account_id_, false))
       .Times(1);
@@ -1037,7 +1006,6 @@
   // time of last login with SAML are not changed.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_saml_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -1051,7 +1019,6 @@
   Mock::VerifyAndClearExpectations(user_manager_);
   // Allow the timer to fire. Verify that the flag enforcing online login is
   // set
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_saml_account_id_, false))
       .Times(0);
@@ -1097,7 +1064,6 @@
   // login is cleared and the time of last login with SAML is updated.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_saml_account_id_, false))
       .Times(1);
@@ -1123,7 +1089,6 @@
   // time of last login with SAML are not changed.
   CreateLimiter();
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_saml_account_id_, _))
       .Times(0);
   limiter_->SignedIn(UserContext::AUTH_FLOW_OFFLINE);
@@ -1189,7 +1154,6 @@
 
   // Set a zero time limit. Verify that the flag enforcing online login is set.
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_,
               SaveForceOnlineSignin(test_saml_account_id_, false))
       .Times(0);
@@ -1227,7 +1191,6 @@
   // Verify that the flag enforcing online login is not
   // changed.
   Mock::VerifyAndClearExpectations(user_manager_);
-  SetUpUserManager();
   EXPECT_CALL(*user_manager_, SaveForceOnlineSignin(test_saml_account_id_, _))
       .Times(0);
 }
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.cc b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
index 8023c087..68b843c7 100644
--- a/chrome/browser/ash/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
@@ -505,9 +505,14 @@
 bool LoginDisplayHostMojo::GetKeyboardRemappedPrefValue(
     const std::string& pref_name,
     int* value) const {
+  if (!focused_pod_account_id_.is_valid())
+    return false;
   user_manager::KnownUser known_user(g_browser_process->local_state());
-  return focused_pod_account_id_.is_valid() &&
-         known_user.GetIntegerPref(focused_pod_account_id_, pref_name, value);
+  absl::optional<int> opt_val =
+      known_user.FindIntPath(focused_pod_account_id_, pref_name);
+  if (value && opt_val.has_value())
+    *value = opt_val.value();
+  return opt_val.has_value();
 }
 
 bool LoginDisplayHostMojo::IsWebUIStarted() const {
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 7b5d5a6..851ae0a 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -1485,8 +1485,9 @@
   }
 
   // Test initial enrollment. This method is shared by the tests for initial
-  // enrollment for a device that is new or in consumer mode.
-  void DoInitialEnrollment() {
+  // enrollment for a device that is new or in consumer mode. |check_fre|
+  // specifies if forced re-enrollment check is needed.
+  void DoInitialEnrollment(bool check_fre) {
     fake_statistics_provider_.SetMachineStatistic(
         system::kEnterpriseManagementEmbargoEndDateKey,
         GenerateEmbargoEndDate(-15 /* days_offset */));
@@ -1506,11 +1507,14 @@
     mock_eula_screen_->ExitScreen(
         EulaScreen::Result::ACCEPTED_WITHOUT_USAGE_STATS_REPORTING);
 
-    // Wait for auto-enrollment controller to encounter the connection error.
-    WaitForAutoEnrollmentState(policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR);
+    if (check_fre) {
+      // Wait for auto-enrollment controller to encounter the connection error.
+      WaitForAutoEnrollmentState(
+          policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR);
 
-    // Let update screen smooth time process (time = 0ms).
-    base::RunLoop().RunUntilIdle();
+      // Let update screen smooth time process (time = 0ms).
+      base::RunLoop().RunUntilIdle();
+    }
 
     CheckCurrentScreen(UpdateView::kScreenId);
     EXPECT_CALL(*mock_update_screen_, HideImpl()).Times(1);
@@ -1523,8 +1527,10 @@
 
     // The error screen shows up if there's no auto-enrollment decision.
     EXPECT_FALSE(StartupUtils::IsOobeCompleted());
-    EXPECT_EQ(AutoEnrollmentCheckScreenView::kScreenId.AsId(),
-              GetErrorScreen()->GetParentScreen());
+    if (check_fre) {
+      EXPECT_EQ(AutoEnrollmentCheckScreenView::kScreenId.AsId(),
+                GetErrorScreen()->GetParentScreen());
+    }
     base::DictionaryValue device_state;
     device_state.SetStringKey(
         policy::kDeviceStateMode,
@@ -1557,7 +1563,7 @@
                        ControlFlowInitialEnrollment) {
   fake_statistics_provider_.ClearMachineStatistic(system::kActivateDateKey);
 
-  DoInitialEnrollment();
+  DoInitialEnrollment(/*check_fre=*/true);
 }
 
 // Tests that a device that is in consumer mode can do another initial
@@ -1568,7 +1574,7 @@
   fake_statistics_provider_.SetMachineStatistic(system::kCheckEnrollmentKey,
                                                 "0");
 
-  DoInitialEnrollment();
+  DoInitialEnrollment(/*check_fre=*/false);
 }
 
 // Tests that a server error occurs during the Initial Enrollment check.  The
diff --git a/chrome/browser/ash/preferences.cc b/chrome/browser/ash/preferences.cc
index 8621db2..54807726 100644
--- a/chrome/browser/ash/preferences.cc
+++ b/chrome/browser/ash/preferences.cc
@@ -1055,8 +1055,8 @@
   for (auto* remap_pref : kLanguageRemapPrefs) {
     if (pref_name == remap_pref || reason != REASON_ACTIVE_USER_CHANGED) {
       const int value = prefs_->GetInteger(remap_pref);
-      user_manager::known_user::SetIntegerPref(user_->GetAccountId(),
-                                               remap_pref, value);
+      user_manager::KnownUser known_user(g_browser_process->local_state());
+      known_user.SetIntegerPref(user_->GetAccountId(), remap_pref, value);
     }
   }
 
@@ -1158,12 +1158,12 @@
   input_method::InputMethodManager::Get()->GetImeKeyboard()->SetAutoRepeatRate(
       rate);
 
-  user_manager::known_user::SetIntegerPref(user_->GetAccountId(),
-                                           prefs::kXkbAutoRepeatDelay,
-                                           rate.initial_delay_in_ms);
-  user_manager::known_user::SetIntegerPref(user_->GetAccountId(),
-                                           prefs::kXkbAutoRepeatInterval,
-                                           rate.repeat_interval_in_ms);
+  user_manager::KnownUser known_user(g_browser_process->local_state());
+  known_user.SetIntegerPref(user_->GetAccountId(), prefs::kXkbAutoRepeatDelay,
+                            rate.initial_delay_in_ms);
+  known_user.SetIntegerPref(user_->GetAccountId(),
+                            prefs::kXkbAutoRepeatInterval,
+                            rate.repeat_interval_in_ms);
 }
 
 void Preferences::ActiveUserChanged(user_manager::User* active_user) {
diff --git a/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.cc b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.cc
new file mode 100644
index 0000000..e2af1f3
--- /dev/null
+++ b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.cc
@@ -0,0 +1,158 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/containers/span.h"
+#include "components/account_manager_core/account.h"
+#include "components/account_manager_core/account_manager_util.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/sync/driver/sync_user_settings.h"
+#include "components/sync/engine/nigori/nigori.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace ash {
+
+namespace {
+
+crosapi::mojom::NigoriKeyPtr NigoriToMojo(const syncer::Nigori& nigori) {
+  std::string deprecated_user_key;
+  std::string encryption_key;
+  std::string mac_key;
+  nigori.ExportKeys(&deprecated_user_key, &encryption_key, &mac_key);
+
+  crosapi::mojom::NigoriKeyPtr mojo_result = crosapi::mojom::NigoriKey::New();
+  mojo_result->encryption_key =
+      std::vector<uint8_t>(encryption_key.begin(), encryption_key.end());
+  mojo_result->mac_key = std::vector<uint8_t>(mac_key.begin(), mac_key.end());
+  return mojo_result;
+}
+
+std::unique_ptr<syncer::Nigori> NigoriFromMojo(
+    const crosapi::mojom::NigoriKey& mojo_key) {
+  const std::string encryption_key(mojo_key.encryption_key.begin(),
+                                   mojo_key.encryption_key.end());
+  const std::string mac_key(mojo_key.mac_key.begin(), mojo_key.mac_key.end());
+  // |user_key| is deprecated, it's safe to pass empty string.
+  return syncer::Nigori::CreateByImport(
+      /*user_key=*/std::string(), encryption_key, mac_key);
+}
+
+}  // namespace
+
+crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting(  // IN-TEST
+    const syncer::Nigori& nigori) {
+  return NigoriToMojo(nigori);
+}
+
+SyncExplicitPassphraseClientAsh::SyncExplicitPassphraseClientAsh(
+    syncer::SyncService* sync_service)
+    : sync_service_(sync_service),
+      previous_passphrase_required_state_(
+          sync_service_->GetUserSettings()->IsPassphraseRequired()) {
+  sync_service_->AddObserver(this);
+}
+
+SyncExplicitPassphraseClientAsh::~SyncExplicitPassphraseClientAsh() {
+  sync_service_->RemoveObserver(this);
+}
+
+void SyncExplicitPassphraseClientAsh::BindReceiver(
+    mojo::PendingReceiver<crosapi::mojom::SyncExplicitPassphraseClient>
+        receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void SyncExplicitPassphraseClientAsh::AddObserver(
+    mojo::PendingRemote<crosapi::mojom::SyncExplicitPassphraseClientObserver>
+        observer) {
+  observers_.Add(std::move(observer));
+}
+
+void SyncExplicitPassphraseClientAsh::GetDecryptionNigoriKey(
+    crosapi::mojom::AccountKeyPtr mojo_account_key,
+    GetDecryptionNigoriKeyCallback callback) {
+  if (!ValidateAccountKey(mojo_account_key)) {
+    std::move(callback).Run(nullptr);
+    return;
+  }
+
+  std::unique_ptr<syncer::Nigori> decryption_key =
+      sync_service_->GetUserSettings()->GetDecryptionNigoriKey();
+  if (!decryption_key) {
+    std::move(callback).Run(nullptr);
+    return;
+  }
+
+  std::move(callback).Run(NigoriToMojo(*decryption_key));
+}
+
+void SyncExplicitPassphraseClientAsh::SetDecryptionNigoriKey(
+    crosapi::mojom::AccountKeyPtr mojo_account_key,
+    crosapi::mojom::NigoriKeyPtr mojo_nigori_key) {
+  if (!ValidateAccountKey(mojo_account_key) || !mojo_nigori_key) {
+    return;
+  }
+
+  std::unique_ptr<syncer::Nigori> nigori_key = NigoriFromMojo(*mojo_nigori_key);
+  if (!nigori_key) {
+    // Deserialization failed, |mojo_nigori_key| doesn't represent an actual
+    // Nigori key.
+    return;
+  }
+  sync_service_->GetUserSettings()->SetDecryptionNigoriKey(
+      std::move(nigori_key));
+}
+
+void SyncExplicitPassphraseClientAsh::OnStateChanged(
+    syncer::SyncService* sync_service) {
+  bool new_passphrase_required_state =
+      sync_service->GetUserSettings()->IsPassphraseRequired();
+  if (new_passphrase_required_state == previous_passphrase_required_state_) {
+    // State change is not relevant for this class.
+    return;
+  }
+
+  if (new_passphrase_required_state) {
+    for (auto& observer : observers_) {
+      observer->OnPassphraseRequired();
+    }
+  } else {
+    // Passphrase required state was resolved, that means that new passphrase is
+    // likely available (modulo some corner cases, like sync reset, but this
+    // should be safe to issue redundant OnPassphraseAvailable() call).
+    for (auto& observer : observers_) {
+      observer->OnPassphraseAvailable();
+    }
+  }
+
+  previous_passphrase_required_state_ = new_passphrase_required_state;
+}
+
+void SyncExplicitPassphraseClientAsh::FlushMojoForTesting() {
+  observers_.FlushForTesting();  // IN-TEST
+}
+
+bool SyncExplicitPassphraseClientAsh::ValidateAccountKey(
+    const crosapi::mojom::AccountKeyPtr& mojo_account_key) const {
+  const absl::optional<account_manager::AccountKey> account_key =
+      account_manager::FromMojoAccountKey(mojo_account_key);
+  if (!account_key.has_value()) {
+    return false;
+  }
+
+  if (account_key->account_type() != account_manager::AccountType::kGaia) {
+    // ActiveDirectory accounts are not supported.
+    return false;
+  }
+
+  return !account_key->id().empty() &&
+         account_key->id() == sync_service_->GetAccountInfo().gaia;
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h
new file mode 100644
index 0000000..c990b7a
--- /dev/null
+++ b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h
@@ -0,0 +1,76 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_SYNC_SYNC_EXPLICIT_PASSPHRASE_CLIENT_ASH_H_
+#define CHROME_BROWSER_ASH_SYNC_SYNC_EXPLICIT_PASSPHRASE_CLIENT_ASH_H_
+
+#include "base/memory/raw_ptr.h"
+#include "chromeos/crosapi/mojom/account_manager.mojom.h"
+#include "chromeos/crosapi/mojom/sync.mojom.h"
+#include "components/sync/driver/sync_service.h"
+#include "components/sync/driver/sync_service_observer.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
+
+namespace syncer {
+class Nigori;
+}
+
+namespace ash {
+
+class SyncExplicitPassphraseClientAsh
+    : public crosapi::mojom::SyncExplicitPassphraseClient,
+      public syncer::SyncServiceObserver {
+ public:
+  // |sync_service| must not be null. |this| must be destroyed before
+  // |sync_service| shutdown.
+  explicit SyncExplicitPassphraseClientAsh(syncer::SyncService* sync_service);
+  SyncExplicitPassphraseClientAsh(
+      const SyncExplicitPassphraseClientAsh& other) = delete;
+  SyncExplicitPassphraseClientAsh& operator=(
+      const SyncExplicitPassphraseClientAsh& other) = delete;
+  ~SyncExplicitPassphraseClientAsh() override;
+
+  void BindReceiver(
+      mojo::PendingReceiver<crosapi::mojom::SyncExplicitPassphraseClient>
+          receiver);
+
+  // crosapi::mojom::AshSyncExplicitPassphraseClient implementation.
+  void AddObserver(
+      mojo::PendingRemote<crosapi::mojom::SyncExplicitPassphraseClientObserver>
+          observer) override;
+  void GetDecryptionNigoriKey(crosapi::mojom::AccountKeyPtr mojo_account_key,
+                              GetDecryptionNigoriKeyCallback callback) override;
+  void SetDecryptionNigoriKey(
+      crosapi::mojom::AccountKeyPtr mojo_account_key,
+      crosapi::mojom::NigoriKeyPtr mojo_nigori_key) override;
+
+  // syncer::SyncServiceObserver implementation.
+  void OnStateChanged(syncer::SyncService* sync_service) override;
+
+  void FlushMojoForTesting();
+
+ private:
+  bool ValidateAccountKey(
+      const crosapi::mojom::AccountKeyPtr& mojo_account_key) const;
+
+  const base::raw_ptr<syncer::SyncService> sync_service_;
+
+  bool previous_passphrase_required_state_;
+
+  // Don't add new members below this. `receivers_` and `observers_` should be
+  // destroyed as soon as `this` is getting destroyed so that we don't deal
+  // with message handling on a partially destroyed object.
+  mojo::ReceiverSet<crosapi::mojom::SyncExplicitPassphraseClient> receivers_;
+  mojo::RemoteSet<crosapi::mojom::SyncExplicitPassphraseClientObserver>
+      observers_;
+};
+
+crosapi::mojom::NigoriKeyPtr NigoriToMojoForTesting(
+    const syncer::Nigori& nigori);
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_SYNC_SYNC_EXPLICIT_PASSPHRASE_CLIENT_ASH_H_
diff --git a/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash_unittest.cc b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash_unittest.cc
new file mode 100644
index 0000000..79ebbc1
--- /dev/null
+++ b/chrome/browser/ash/sync/sync_explicit_passphrase_client_ash_unittest.cc
@@ -0,0 +1,237 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/sync/sync_explicit_passphrase_client_ash.h"
+
+#include "base/test/task_environment.h"
+#include "chromeos/crosapi/mojom/sync.mojom-test-utils.h"
+#include "components/sync/driver/mock_sync_service.h"
+#include "components/sync/driver/sync_user_settings_mock.h"
+#include "components/sync/engine/nigori/key_derivation_params.h"
+#include "components/sync/engine/nigori/nigori.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash {
+
+namespace {
+
+using testing::_;
+using testing::Eq;
+using testing::NotNull;
+using testing::Return;
+
+std::unique_ptr<syncer::Nigori> MakeTestNigoriKey() {
+  return syncer::Nigori::CreateByDerivation(
+      syncer::KeyDerivationParams::CreateForPbkdf2(), /*password=*/"password");
+}
+
+crosapi::mojom::NigoriKeyPtr MakeTestMojoNigoriKey() {
+  std::unique_ptr<syncer::Nigori> nigori_key = MakeTestNigoriKey();
+  return NigoriToMojoForTesting(*nigori_key);
+}
+
+class TestSyncExplicitPassphraseClientObserver
+    : public crosapi::mojom::
+          SyncExplicitPassphraseClientObserverInterceptorForTesting {
+ public:
+  TestSyncExplicitPassphraseClientObserver() = default;
+  TestSyncExplicitPassphraseClientObserver(
+      const TestSyncExplicitPassphraseClientObserver& other) = delete;
+  TestSyncExplicitPassphraseClientObserver& operator=(
+      const TestSyncExplicitPassphraseClientObserver& other) = delete;
+  ~TestSyncExplicitPassphraseClientObserver() override = default;
+
+  void Observe(SyncExplicitPassphraseClientAsh* client) {
+    auto remote = receiver_.BindNewPipeAndPassRemote();
+    client->AddObserver(std::move(remote));
+  }
+
+  int GetNumOnPassphraseRequiredCalls() const {
+    return num_on_passphrase_required_calls_;
+  }
+
+  int GetNumOnPassphraseAvailableCalls() const {
+    return num_on_passphrase_available_calls_;
+  }
+
+  // crosapi::mojom::SyncExplicitPassphraseClientObserverInterceptorForTesting
+  // overrides:
+  SyncExplicitPassphraseClientObserver* GetForwardingInterface() override {
+    return this;
+  }
+
+  void OnPassphraseRequired() override { num_on_passphrase_required_calls_++; }
+
+  void OnPassphraseAvailable() override {
+    num_on_passphrase_available_calls_++;
+  }
+
+ private:
+  int num_on_passphrase_required_calls_ = 0;
+  int num_on_passphrase_available_calls_ = 0;
+
+  mojo::Receiver<crosapi::mojom::SyncExplicitPassphraseClientObserver>
+      receiver_{this};
+};
+
+class SyncExplicitPassphraseClientAshTest : public testing::Test {
+ public:
+  SyncExplicitPassphraseClientAshTest() : client_(&sync_service_) {
+    sync_account_info_.gaia = "user1";
+  }
+
+  SyncExplicitPassphraseClientAshTest(
+      const SyncExplicitPassphraseClientAshTest&) = delete;
+  SyncExplicitPassphraseClientAshTest& operator=(
+      const SyncExplicitPassphraseClientAshTest&) = delete;
+  ~SyncExplicitPassphraseClientAshTest() = default;
+
+  void SetUp() override {
+    ON_CALL(sync_service_, GetAccountInfo())
+        .WillByDefault(Return(sync_account_info_));
+    client_.BindReceiver(client_remote_.BindNewPipeAndPassReceiver());
+    client_async_waiter_ = std::make_unique<
+        crosapi::mojom::SyncExplicitPassphraseClientAsyncWaiter>(&client_);
+  }
+
+  SyncExplicitPassphraseClientAsh* client() { return &client_; }
+
+  crosapi::mojom::SyncExplicitPassphraseClientAsyncWaiter*
+  client_async_waiter() {
+    return client_async_waiter_.get();
+  }
+
+  syncer::MockSyncService* sync_service() { return &sync_service_; }
+
+  syncer::SyncUserSettingsMock* sync_user_settings() {
+    return sync_service_.GetMockUserSettings();
+  }
+
+  const CoreAccountInfo& sync_account_info() const {
+    return sync_account_info_;
+  }
+
+  crosapi::mojom::AccountKeyPtr GetSyncingAccountKey() const {
+    crosapi::mojom::AccountKeyPtr account_key =
+        crosapi::mojom::AccountKey::New();
+    account_key->id = sync_account_info_.gaia;
+    account_key->account_type = crosapi::mojom::AccountType::kGaia;
+    return account_key;
+  }
+
+ private:
+  base::test::SingleThreadTaskEnvironment task_environment_;
+
+  testing::NiceMock<syncer::MockSyncService> sync_service_;
+
+  SyncExplicitPassphraseClientAsh client_;
+  mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient> client_remote_;
+  std::unique_ptr<crosapi::mojom::SyncExplicitPassphraseClientAsyncWaiter>
+      client_async_waiter_;
+
+  CoreAccountInfo sync_account_info_;
+};
+
+TEST_F(SyncExplicitPassphraseClientAshTest, ShouldGetDecryptionKey) {
+  ON_CALL(*sync_user_settings(), GetDecryptionNigoriKey())
+      .WillByDefault(MakeTestNigoriKey);
+
+  crosapi::mojom::NigoriKeyPtr nigori_key;
+  client_async_waiter()->GetDecryptionNigoriKey(GetSyncingAccountKey(),
+                                                &nigori_key);
+  ASSERT_FALSE(nigori_key.is_null());
+
+  crosapi::mojom::NigoriKeyPtr expected_nigori_key = MakeTestMojoNigoriKey();
+  EXPECT_THAT(nigori_key->encryption_key,
+              Eq(expected_nigori_key->encryption_key));
+  EXPECT_THAT(nigori_key->mac_key, Eq(expected_nigori_key->mac_key));
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest,
+       ShouldValidateAccountWhenGettingDecryptionKey) {
+  crosapi::mojom::AccountKeyPtr wrong_account_key =
+      crosapi::mojom::AccountKey::New();
+  wrong_account_key->id = "user2";
+  wrong_account_key->account_type = crosapi::mojom::AccountType::kGaia;
+
+  crosapi::mojom::NigoriKeyPtr nigori_key;
+  client_async_waiter()->GetDecryptionNigoriKey(std::move(wrong_account_key),
+                                                &nigori_key);
+  EXPECT_TRUE(nigori_key.is_null());
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest,
+       ShouldHandleAbsenseOfKeyWhenGettingDecryptionKey) {
+  crosapi::mojom::NigoriKeyPtr nigori_key;
+  client_async_waiter()->GetDecryptionNigoriKey(GetSyncingAccountKey(),
+                                                &nigori_key);
+  EXPECT_TRUE(nigori_key.is_null());
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest, ShouldSetDecryptionKey) {
+  EXPECT_CALL(*sync_user_settings(), SetDecryptionNigoriKey(NotNull()));
+  client()->SetDecryptionNigoriKey(GetSyncingAccountKey(),
+                                   MakeTestMojoNigoriKey());
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest,
+       ShouldValidateAccountWhenSettingDecryptionKey) {
+  crosapi::mojom::AccountKeyPtr wrong_account_key =
+      crosapi::mojom::AccountKey::New();
+  wrong_account_key->id = "user2";
+  wrong_account_key->account_type = crosapi::mojom::AccountType::kGaia;
+
+  EXPECT_CALL(*sync_user_settings(), SetDecryptionNigoriKey(_)).Times(0);
+  client()->SetDecryptionNigoriKey(std::move(wrong_account_key),
+                                   MakeTestMojoNigoriKey());
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest,
+       ShouldHandleNullKeyWhenSettingDecryptionKey) {
+  EXPECT_CALL(*sync_user_settings(), SetDecryptionNigoriKey(_)).Times(0);
+  client()->SetDecryptionNigoriKey(GetSyncingAccountKey(), nullptr);
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest,
+       ShouldHandleInvalidKeyWhenSettingDecryptionKey) {
+  EXPECT_CALL(*sync_user_settings(), SetDecryptionNigoriKey(_)).Times(0);
+
+  crosapi::mojom::NigoriKeyPtr mojo_nigori_key =
+      crosapi::mojom::NigoriKey::New();
+  // Nigori deserialization fails with a wrong key length.
+  mojo_nigori_key->encryption_key = {1, 2, 3};
+  mojo_nigori_key->mac_key = {1, 2, 3};
+
+  EXPECT_CALL(*sync_user_settings(), SetDecryptionNigoriKey(_)).Times(0);
+  client()->SetDecryptionNigoriKey(GetSyncingAccountKey(),
+                                   std::move(mojo_nigori_key));
+}
+
+TEST_F(SyncExplicitPassphraseClientAshTest, ShouldNotifyObserver) {
+  TestSyncExplicitPassphraseClientObserver observer;
+  observer.Observe(client());
+
+  ASSERT_THAT(observer.GetNumOnPassphraseAvailableCalls(), Eq(0));
+  ASSERT_THAT(observer.GetNumOnPassphraseRequiredCalls(), Eq(0));
+
+  // Mimic entering passphrase required state.
+  ON_CALL(*sync_user_settings(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  client()->OnStateChanged(sync_service());
+  client()->FlushMojoForTesting();
+  EXPECT_THAT(observer.GetNumOnPassphraseAvailableCalls(), Eq(0));
+  EXPECT_THAT(observer.GetNumOnPassphraseRequiredCalls(), Eq(1));
+
+  // Mimic passphrase being entered by the user.
+  ON_CALL(*sync_user_settings(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  client()->OnStateChanged(sync_service());
+  client()->FlushMojoForTesting();
+  EXPECT_THAT(observer.GetNumOnPassphraseAvailableCalls(), Eq(1));
+  EXPECT_THAT(observer.GetNumOnPassphraseRequiredCalls(), Eq(1));
+}
+
+}  // namespace
+}  // namespace ash
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc
index 1e376c5..5db6eea 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
+#include "chrome/browser/web_applications/web_app_install_manager.h"
+#include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "components/webapps/browser/banners/app_banner_metrics.h"
 #include "components/webapps/browser/banners/app_banner_settings_helper.h"
@@ -90,7 +92,7 @@
   auto* provider = web_app::WebAppProvider::GetForWebApps(profile);
   // May be null in unit tests e.g. TabDesktopMediaListTest.*.
   if (provider)
-    registrar_observation_.Observe(&provider->registrar());
+    install_manager_observation_.Observe(&provider->install_manager());
 }
 
 AppBannerManagerDesktop::~AppBannerManagerDesktop() { }
@@ -235,8 +237,8 @@
     RecheckInstallabilityForLoadedPage(validated_url(), true);
 }
 
-void AppBannerManagerDesktop::OnAppRegistrarDestroyed() {
-  registrar_observation_.Reset();
+void AppBannerManagerDesktop::OnWebAppInstallManagerDestroyed() {
+  install_manager_observation_.Reset();
 }
 
 void AppBannerManagerDesktop::CreateWebApp(WebappInstallSource install_source) {
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h
index ae437c5..529382b 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.h
+++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -12,7 +12,8 @@
 #include "base/scoped_observation.h"
 #include "chrome/browser/web_applications/app_registrar_observer.h"
 #include "chrome/browser/web_applications/web_app_id.h"
-#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_install_manager.h"
+#include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "components/webapps/browser/banners/app_banner_manager.h"
 #include "content/public/browser/web_contents_user_data.h"
 
@@ -31,7 +32,7 @@
 class AppBannerManagerDesktop
     : public AppBannerManager,
       public content::WebContentsUserData<AppBannerManagerDesktop>,
-      public web_app::AppRegistrarObserver {
+      public web_app::WebAppInstallManagerObserver {
  public:
   AppBannerManagerDesktop(const AppBannerManagerDesktop&) = delete;
   AppBannerManagerDesktop& operator=(const AppBannerManagerDesktop&) = delete;
@@ -89,20 +90,20 @@
                          double score,
                          site_engagement::EngagementType type) override;
 
-  // web_app::AppRegistrarObserver:
+  // web_app::WebAppInstallManagerObserver:
   void OnWebAppInstalled(const web_app::AppId& app_id) override;
   void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override;
   void OnWebAppUninstalled(const web_app::AppId& app_id) override;
-  void OnAppRegistrarDestroyed() override;
+  void OnWebAppInstallManagerDestroyed() override;
 
   void CreateWebApp(WebappInstallSource install_source);
 
   raw_ptr<extensions::ExtensionRegistry> extension_registry_;
   web_app::AppId uninstalling_app_id_;
 
-  base::ScopedObservation<web_app::WebAppRegistrar,
-                          web_app::AppRegistrarObserver>
-      registrar_observation_{this};
+  base::ScopedObservation<web_app::WebAppInstallManager,
+                          web_app::WebAppInstallManagerObserver>
+      install_manager_observation_{this};
 
   base::WeakPtrFactory<AppBannerManagerDesktop> weak_factory_{this};
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f7057b8..63d30eb 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3119,6 +3119,8 @@
     "../ash/sync/sync_error_notifier.h",
     "../ash/sync/sync_error_notifier_factory.cc",
     "../ash/sync/sync_error_notifier_factory.h",
+    "../ash/sync/sync_explicit_passphrase_client_ash.cc",
+    "../ash/sync/sync_explicit_passphrase_client_ash.h",
     "../ash/system/automatic_reboot_manager.cc",
     "../ash/system/automatic_reboot_manager.h",
     "../ash/system/automatic_reboot_manager_observer.h",
@@ -4612,6 +4614,7 @@
     "../ash/startup_settings_cache_unittest.cc",
     "../ash/sync/os_sync_util_unittest.cc",
     "../ash/sync/sync_error_notifier_unittest.cc",
+    "../ash/sync/sync_explicit_passphrase_client_ash_unittest.cc",
     "../ash/system/automatic_reboot_manager_unittest.cc",
     "../ash/system/device_disabling_manager_unittest.cc",
     "../ash/system/kernel_feature_manager_unittest.cc",
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 029b7e92..316db2d 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -763,7 +763,7 @@
   {
     "name": "clean-undecryptable-passwords",
     "owners": [ "derinel@google.com", "mamir" ],
-    "expiry_milestone": 99
+    "expiry_milestone": 102
   },
   {
     "name": "clear-cross-site-cross-browsing-context-group-window-name",
@@ -2918,6 +2918,11 @@
     "expiry_milestone": 92
   },
   {
+    "name": "enable-web-bluetooth",
+    "owners": [ "web-bluetooth@google.com" ],
+    "expiry_milestone": 110
+  },
+  {
     "name": "enable-web-bluetooth-new-permissions-backend",
     "owners": [ "web-bluetooth@google.com" ],
     "expiry_milestone": 100
@@ -3330,6 +3335,11 @@
     "expiry_milestone": 100
   },
   {
+    "name": "force-password-initial-sync-when-decryption-fails",
+    "owners": [ "derinel@google.com", "mamir" ],
+    "expiry_milestone": 102
+  },
+  {
     "name": "force-show-continue-section",
     "owners":["anasalazar@chromium.org", "gzadina@google.com"],
     "expiry_milestone": 101
@@ -5312,6 +5322,11 @@
     "expiry_milestone": 100
   },
   {
+    "name": "skip-undecryptable-passwords",
+    "owners": [ "derinel@google.com", "mamir" ],
+    "expiry_milestone": 102
+  },
+  {
     "name": "smart-lock-ui-revamp",
     "owners": [ "cclem", "better-together-dev@google.com" ],
     "expiry_milestone": 101
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d557a62..40269e08 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2636,6 +2636,10 @@
 const char kWallpaperPerDeskDescription[] =
     "Allow users to set different wallpapers on each of their active desks";
 
+const char kWebBluetoothName[] = "Web Bluetooth";
+const char kWebBluetoothDescription[] =
+    "Enables the Web Bluetooth API on platforms without official support";
+
 const char kWebBluetoothNewPermissionsBackendName[] =
     "Use the new permissions backend for Web Bluetooth";
 const char kWebBluetoothNewPermissionsBackendDescription[] =
@@ -5471,8 +5475,22 @@
 const char kCleanUndecryptablePasswordsLinuxDescription[] =
     "Deletes the undecryptable passwords from the local database to enable "
     "syncing all passwords during the initial sync.";
+const char kForcePasswordInitialSyncWhenDecryptionFailsName[] =
+    "Force initial sync to clean local undecryptable passwords during startup";
+const char kForcePasswordInitialSyncWhenDecryptionFailsDescription[] =
+    "During startup checks if there are undecryptable passwords in the local "
+    "storage and requests initial sync.";
 #endif  // BUILDFLAG(IS_LINUX)
 
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+const char kSkipUndecryptablePasswordsName[] =
+    "Skip undecryptable passwords to use the available decryptable "
+    "passwords.";
+const char kSkipUndecryptablePasswordsDescription[] =
+    "Makes the decryptable passwords available in the password manager when "
+    "there are undecryptable ones.";
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+
 // Feature flags --------------------------------------------------------------
 
 #if defined(DCHECK_IS_CONFIGURABLE)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 14ef71f..5a346828 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1502,6 +1502,9 @@
 extern const char kWallpaperPerDeskName[];
 extern const char kWallpaperPerDeskDescription[];
 
+extern const char kWebBluetoothName[];
+extern const char kWebBluetoothDescription[];
+
 extern const char kWebBluetoothNewPermissionsBackendName[];
 extern const char kWebBluetoothNewPermissionsBackendDescription[];
 
@@ -3157,8 +3160,16 @@
 
 extern const char kCleanUndecryptablePasswordsLinuxName[];
 extern const char kCleanUndecryptablePasswordsLinuxDescription[];
+
+extern const char kForcePasswordInitialSyncWhenDecryptionFailsName[];
+extern const char kForcePasswordInitialSyncWhenDecryptionFailsDescription[];
 #endif  // BUILDFLAG(IS_LINUX)
 
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+extern const char kSkipUndecryptablePasswordsName[];
+extern const char kSkipUndecryptablePasswordsDescription[];
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
+
 // Feature flags --------------------------------------------------------------
 
 #if defined(DCHECK_IS_CONFIGURABLE)
diff --git a/chrome/browser/lacros/browser_service_lacros.cc b/chrome/browser/lacros/browser_service_lacros.cc
index 6f12f47..fa2c5bd 100644
--- a/chrome/browser/lacros/browser_service_lacros.cc
+++ b/chrome/browser/lacros/browser_service_lacros.cc
@@ -18,6 +18,8 @@
 #include "chrome/browser/lacros/system_logs/lacros_system_log_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/sessions/session_restore.h"
 #include "chrome/browser/sessions/session_service_factory.h"
 #include "chrome/browser/ui/browser.h"
@@ -155,6 +157,13 @@
                      weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
 }
 
+void BrowserServiceLacros::NewGuestWindow(NewGuestWindowCallback callback) {
+  if (profiles::IsGuestModeEnabled())
+    profiles::SwitchToGuestProfile();
+
+  std::move(callback).Run();
+}
+
 void BrowserServiceLacros::NewWindowForDetachingTab(
     const std::u16string& tab_id,
     const std::u16string& group_id,
diff --git a/chrome/browser/lacros/browser_service_lacros.h b/chrome/browser/lacros/browser_service_lacros.h
index 5984124..f9106cc 100644
--- a/chrome/browser/lacros/browser_service_lacros.h
+++ b/chrome/browser/lacros/browser_service_lacros.h
@@ -37,6 +37,7 @@
                  NewWindowCallback callback) override;
   void NewFullscreenWindow(const GURL& url,
                            NewFullscreenWindowCallback callback) override;
+  void NewGuestWindow(NewGuestWindowCallback callback) override;
   void NewWindowForDetachingTab(
       const std::u16string& tab_id,
       const std::u16string& group_id,
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
index fccffdd1..11fb8cd 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -17,6 +17,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "chrome/browser/lookalikes/lookalike_url_blocking_page.h"
 #include "chrome/browser/lookalikes/lookalike_url_controller_client.h"
 #include "chrome/browser/lookalikes/lookalike_url_service.h"
@@ -53,6 +54,23 @@
     "OptimizeLookalikeUrlNavigationThrottle",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Records latency histograms for an invocation of PerformChecks() just before
+// it will return a value of PROCEED.
+void RecordPerformCheckLatenciesForAllowedNavigation(
+    base::TimeTicks check_start_time,
+    base::TimeDelta is_lookalike_url_duration,
+    base::TimeDelta get_domain_info_duration) {
+  UMA_HISTOGRAM_TIMES(
+      "NavigationSuggestion.PerformChecksDelayBeforeAllowingNavigation",
+      base::TimeTicks::Now() - check_start_time);
+  UMA_HISTOGRAM_TIMES(
+      "NavigationSuggestion.IsLookalikeUrlDelayBeforeAllowingNavigation",
+      is_lookalike_url_duration);
+  UMA_HISTOGRAM_TIMES(
+      "NavigationSuggestion.GetDomainInfoDelayBeforeAllowingNavigation",
+      get_domain_info_duration);
+}
+
 }  // namespace
 
 LookalikeUrlNavigationThrottle::LookalikeUrlNavigationThrottle(
@@ -282,6 +300,8 @@
 
 ThrottleCheckResult LookalikeUrlNavigationThrottle::PerformChecks(
     const std::vector<DomainInfo>& engaged_sites) {
+  base::TimeTicks perform_checks_start = base::TimeTicks::Now();
+
   // The last URL in the redirect chain must be the same as the commit URL,
   // or the navigation is a loadData navigation (where the base URL is saved in
   // the redirect chain, instead of the commit URL).
@@ -296,19 +316,30 @@
   const GURL& first_url = navigation_handle()->GetRedirectChain()[0];
   const GURL& last_url = navigation_handle()->GetURL();
 
+  base::TimeTicks is_lookalike_url_start = base::TimeTicks::Now();
+
   // If first_url and last_url share a hostname, then only check last_url.
   // This saves time, and avoids clouding metrics.
   LookalikeUrlMatchType first_match_type;
   GURL first_suggested_url;
+  base::TimeDelta first_url_get_domain_info_duration;
   bool first_is_lookalike =
       first_url.host() != last_url.host() &&
       IsLookalikeUrl(first_url, engaged_sites, &first_match_type,
-                     &first_suggested_url);
+                     &first_suggested_url, &first_url_get_domain_info_duration);
 
   LookalikeUrlMatchType last_match_type;
   GURL last_suggested_url;
-  bool last_is_lookalike = IsLookalikeUrl(
-      last_url, engaged_sites, &last_match_type, &last_suggested_url);
+  base::TimeDelta last_url_get_domain_info_duration;
+  bool last_is_lookalike =
+      IsLookalikeUrl(last_url, engaged_sites, &last_match_type,
+                     &last_suggested_url, &last_url_get_domain_info_duration);
+
+  base::TimeDelta is_lookalike_url_duration =
+      base::TimeTicks::Now() - is_lookalike_url_start;
+  base::TimeDelta total_get_domain_info_duration =
+      first_url_get_domain_info_duration;
+  total_get_domain_info_duration += last_url_get_domain_info_duration;
 
   // If the first URL is a lookalike, but we ended up on the suggested site
   // anyway, don't warn.
@@ -340,6 +371,9 @@
   }
 
   if (!first_is_lookalike && !last_is_lookalike) {
+    RecordPerformCheckLatenciesForAllowedNavigation(
+        perform_checks_start, is_lookalike_url_duration,
+        total_get_domain_info_duration);
     return NavigationThrottle::PROCEED;
   }
   // IMPORTANT: Do not modify first_is_lookalike or last_is_lookalike beyond
@@ -385,6 +419,9 @@
       source_id, match_type,
       LookalikeUrlBlockingPageUserAction::kInterstitialNotShown,
       first_is_lookalike);
+  RecordPerformCheckLatenciesForAllowedNavigation(
+      perform_checks_start, is_lookalike_url_duration,
+      total_get_domain_info_duration);
   return NavigationThrottle::PROCEED;
 }
 
@@ -392,7 +429,10 @@
     const GURL& url,
     const std::vector<DomainInfo>& engaged_sites,
     LookalikeUrlMatchType* match_type,
-    GURL* suggested_url) {
+    GURL* suggested_url,
+    base::TimeDelta* get_domain_info_duration) {
+  DCHECK(get_domain_info_duration->is_zero());
+
   if (!url.SchemeIsHTTPOrHTTPS()) {
     return false;
   }
@@ -429,7 +469,10 @@
   }
 
   // GetDomainInfo() is expensive, so do possible early-abort checks first.
+  base::TimeTicks get_domain_info_start = base::TimeTicks::Now();
   const DomainInfo navigated_domain = GetDomainInfo(url);
+  *get_domain_info_duration = base::TimeTicks::Now() - get_domain_info_start;
+
   if (IsTopDomain(navigated_domain)) {
     return false;
   }
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
index cb385d63..a4eb503 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.h
@@ -76,10 +76,14 @@
 
   // Returns whether |url| is a lookalike, setting |match_type| and
   // |suggested_url| appropriately. Used in PerformChecks() on a per-URL basis.
+  // |get_domain_info_duration| should hold zero when IsLookalikeUrl() is
+  // invoked. After invocation, it will hold the duration spent in
+  // GetDomainInfo() if GetDomainInfo() was invoked.
   bool IsLookalikeUrl(const GURL& url,
                       const std::vector<DomainInfo>& engaged_sites,
                       LookalikeUrlMatchType* match_type,
-                      GURL* suggested_url);
+                      GURL* suggested_url,
+                      base::TimeDelta* get_domain_info_duration);
 
   // Shows a full page interstitial. |safe_domain| is the domain suggested as
   // safe by the interstitial. |lookalike_domain| is the domain that triggered
diff --git a/chrome/browser/password_manager/android/password_manager_android_browsertest.cc b/chrome/browser/password_manager/android/password_manager_android_browsertest.cc
new file mode 100644
index 0000000..eb4fe728
--- /dev/null
+++ b/chrome/browser/password_manager/android/password_manager_android_browsertest.cc
@@ -0,0 +1,102 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/password_manager/passwords_navigation_observer.h"
+#include "chrome/test/base/android/android_browser_test.h"
+#include "chrome/test/base/chrome_test_utils.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/password_manager/content/browser/content_password_manager_driver.h"
+#include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
+#include "content/public/test/browser_test.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+autofill::PasswordFormFillData GetTestFillData() {
+  autofill::PasswordFormFillData fill_data;
+  autofill::FormFieldData username_field;
+  username_field.name = u"username_field";
+  fill_data.username_field = username_field;
+  autofill::FormFieldData password_field;
+  password_field.name = u"password_field";
+  password_field.form_control_type = "password";
+  fill_data.password_field = password_field;
+  // Renderer IDs should match real elements' IDs. They cannot be retrieved in a
+  // content::BrowserTestBase, so they are guessed based on the fact the
+  // username and password fields are the first two elements on the page.
+  fill_data.username_field.unique_renderer_id = autofill::FieldRendererId(1);
+  fill_data.password_field.unique_renderer_id = autofill::FieldRendererId(2);
+  return fill_data;
+}
+
+}  // namespace
+
+class PasswordManagerAndroidBrowserTest : public AndroidBrowserTest {
+ public:
+  PasswordManagerAndroidBrowserTest()
+      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+  ~PasswordManagerAndroidBrowserTest() override = default;
+
+  content::WebContents* GetActiveWebContents() {
+    return chrome_test_utils::GetActiveWebContents(this);
+  }
+
+  void SetUpOnMainThread() override {
+    // Map all out-going DNS lookups to the local server. This must be used in
+    // conjunction with switches::kIgnoreCertificateErrors to work.
+    host_resolver()->AddRule("*", "127.0.0.1");
+
+    // Setup HTTPS server serving files from standard test directory.
+    static constexpr base::FilePath::CharType kDocRoot[] =
+        FILE_PATH_LITERAL("chrome/test/data");
+    https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
+    ASSERT_TRUE(https_server_.Start());
+  }
+
+  void NavigateToFile(const std::string& file_path) {
+    PasswordsNavigationObserver observer(GetActiveWebContents());
+    EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(),
+                                       https_server_.GetURL(file_path)));
+    observer.Wait();
+  }
+
+ private:
+  net::EmbeddedTestServer https_server_;
+};
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerAndroidBrowserTest, TriggerSubmission) {
+  NavigateToFile("/password/simple_password.html");
+
+  password_manager::ContentPasswordManagerDriverFactory* driver_factory =
+      password_manager::ContentPasswordManagerDriverFactory::FromWebContents(
+          GetActiveWebContents());
+  password_manager::ContentPasswordManagerDriver* driver =
+      driver_factory->GetDriverForFrame(GetActiveWebContents()->GetMainFrame());
+
+  PasswordsNavigationObserver observer(GetActiveWebContents());
+  observer.SetPathToWaitFor("/password/done.html");
+
+  // Send a fill data to render.
+  autofill::PasswordFormFillData fill_data = GetTestFillData();
+  // Don't fill right now, just inform the rendered that the form is fillable.
+  // To make the test closer to TouchToFill, use |FillSuggestion| to fill a
+  // credential later.
+  fill_data.wait_for_username = true;
+  driver->FillPasswordForm(fill_data);
+
+  // A user taps the username field.
+  ASSERT_TRUE(content::ExecuteScript(
+      GetActiveWebContents(),
+      "document.getElementById('username_field').focus();"));
+
+  // A user accepts a credential in TouchToFill. That fills in the credential
+  // and submits it.
+  driver->FillSuggestion(u"username", u"password");
+  driver->TriggerFormSubmission();
+
+  observer.Wait();
+}
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index 4614476..6a7e2d0 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -188,8 +188,13 @@
     called_set_logging_state_ = true;
     logging_state_active_ = active;
   }
+
   void TouchToFillClosed(bool show_virtual_keyboard) override {}
 
+#if BUILDFLAG(IS_ANDROID)
+  void TriggerFormSubmission() override {}
+#endif
+
   // Records whether SetLoggingState() gets called.
   bool called_set_logging_state_ = false;
   // Records data received via SetLoggingState() call.
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 465d1d2..d235bba0 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -5,33 +5,78 @@
 #include "chrome/browser/prerender/prerender_manager.h"
 
 #include "chrome/browser/prerender/prerender_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "components/omnibox/browser/base_search_provider.h"
+#include "components/search_engines/template_url_service.h"
 #include "content/public/browser/page.h"
 
+namespace {
+
+std::u16string ExtractSearchTermsFromURL(content::WebContents& web_contents,
+                                         const GURL& url) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents.GetBrowserContext());
+  if (!profile)
+    return u"";
+  auto* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(profile);
+  // Can be nullptr in unit tests.
+  if (!template_url_service)
+    return u"";
+  auto* default_search_provider =
+      template_url_service->GetDefaultSearchProvider();
+  DCHECK(default_search_provider);
+  std::u16string matched_search_terms;
+  default_search_provider->ExtractSearchTermsFromURL(
+      url, template_url_service->search_terms_data(), &matched_search_terms);
+  return matched_search_terms;
+}
+
+// Returns true when the two given URLs are considered as navigating to the same
+// search term.
+bool IsSearchDestinationMatch(const std::u16string& prerendered_search_terms,
+                              content::WebContents& web_contents,
+                              const GURL& navigation_url) {
+  DCHECK(!prerendered_search_terms.empty());
+  std::u16string matched_search_terms =
+      ExtractSearchTermsFromURL(web_contents, navigation_url);
+  return matched_search_terms == prerendered_search_terms;
+}
+
+}  // namespace
 PrerenderManager::~PrerenderManager() = default;
 
 void PrerenderManager::PrimaryPageChanged(content::Page& page) {
-  prerender_handle_.reset();
+  search_prerender_handle_.reset();
 }
 
-void PrerenderManager::Start(const GURL& prerendering_url,
-                             TriggerReason reason) {
-  // Currently some prerenders bypass this mechanism, and this class only
-  // handles search suggestions.
-  // TODO(https://crbug.com/1278634): Make AutocompleteActionPredictor trigger
-  // prerendering via PrerenderManager, to ensure all prerenders are controlled
-  // in the same place.
-  DCHECK_EQ(TriggerReason::kSearchSuggestion, reason);
-  if (prerender_handle_ &&
-      prerender_handle_->GetInitialPrerenderingUrl() == prerendering_url) {
+void PrerenderManager::StartPrerenderAutocompleteMatch(
+    const AutocompleteMatch& match) {
+  DCHECK(AutocompleteMatch::IsSearchType(match.type));
+  TemplateURLRef::SearchTermsArgs& search_terms_args =
+      *(match.search_terms_args);
+  std::u16string search_terms = search_terms_args.search_terms;
+
+  // Do not re-prerender the same saerch result.
+  if (search_prerender_handle_ && prerendered_search_terms_ == search_terms) {
     return;
   }
-  prerender_handle_.reset();
-  prerender_handle_ = web_contents()->StartPrerendering(
-      prerendering_url, content::PrerenderTriggerType::kEmbedder,
+  search_prerender_handle_.reset();
+  prerendered_search_terms_ = search_terms;
+  base::RepeatingCallback<bool(const GURL&)> url_match_predicate =
+      base::BindRepeating(&IsSearchDestinationMatch,
+                          std::ref(prerendered_search_terms_),
+                          std::ref(*web_contents()));
+
+  // TODO(https://crbug.com/1278634): Make up a destination url based on
+  // DefaultSearchProvider. This can be differ from `match.destination_url`.
+  search_prerender_handle_ = web_contents()->StartPrerendering(
+      match.destination_url, content::PrerenderTriggerType::kEmbedder,
       prerender_utils::kDefaultSearchEngineMetricSuffix,
       ui::PageTransitionFromInt(ui::PAGE_TRANSITION_GENERATED |
-                                ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
+                                ui::PAGE_TRANSITION_FROM_ADDRESS_BAR),
+      std::move(url_match_predicate));
 }
 
 PrerenderManager::PrerenderManager(content::WebContents* web_contents)
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index e5b8c64e..7ef66c76 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -21,11 +21,6 @@
 class PrerenderManager : public content::WebContentsObserver,
                          public content::WebContentsUserData<PrerenderManager> {
  public:
-  enum TriggerReason {
-    kUrlInputPrediction = 0,
-    kSearchSuggestion = 1,
-  };
-
   PrerenderManager(const PrerenderManager&) = delete;
   PrerenderManager& operator=(const PrerenderManager&) = delete;
 
@@ -36,20 +31,22 @@
 
   // The entry of prerender.
   // Calling this method will lead to the cancellation of the previous prerender
-  // if the given url is differ from the ongoing one's.
+  // if the given `match`'s search terms are differ from the ongoing one's.
   // TODO(https://crbug.com/1278634): return a TriggerResult enum so that
   // callers can record some metrics if they want.
-  void Start(const GURL& prerendering_url, TriggerReason reason);
+  void StartPrerenderAutocompleteMatch(const AutocompleteMatch& match);
 
-  content::PrerenderHandle* prerender_handle_for_testing() {
-    return prerender_handle_.get();
+  content::PrerenderHandle* search_prerender_handle_for_testing() {
+    return search_prerender_handle_.get();
   }
 
  private:
   explicit PrerenderManager(content::WebContents* web_contents);
   friend class content::WebContentsUserData<PrerenderManager>;
 
-  std::unique_ptr<content::PrerenderHandle> prerender_handle_;
+  std::unique_ptr<content::PrerenderHandle> search_prerender_handle_;
+  // Stores the search terms that `search_prerender_handle_` is prerendering.
+  std::u16string prerendered_search_terms_;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 };
diff --git a/chrome/browser/prerender/prerender_manager_unittest.cc b/chrome/browser/prerender/prerender_manager_unittest.cc
index db97bc2..a7c34319 100644
--- a/chrome/browser/prerender/prerender_manager_unittest.cc
+++ b/chrome/browser/prerender/prerender_manager_unittest.cc
@@ -41,13 +41,35 @@
 
   content::WebContents* GetActiveWebContents() { return web_contents(); }
 
-  GURL GetUrl(const std::string& path) { return test_server_.GetURL(path); }
+  GURL GetSearchSuggestionUrl(const std::string& search_site,
+                              const std::string& original_query,
+                              const std::string& search_terms) {
+    return test_server_.GetURL(search_site + "?q=" + search_terms +
+                               "&oq=" + original_query);
+  }
 
   content::WebContentsTester* web_contents_tester() {
     return content::WebContentsTester::For(web_contents());
   }
 
  protected:
+  AutocompleteMatch CreateSearchSuggestionMatch(
+      const std::string& search_site,
+      const std::string& original_query,
+      const std::string& search_terms) {
+    AutocompleteMatch match;
+    match.search_terms_args = std::make_unique<TemplateURLRef::SearchTermsArgs>(
+        base::UTF8ToUTF16(search_terms));
+    match.search_terms_args->original_query = base::UTF8ToUTF16(original_query);
+    match.destination_url =
+        GetSearchSuggestionUrl(search_site, original_query, search_terms);
+    match.keyword = base::UTF8ToUTF16(original_query);
+    match.RecordAdditionalInfo("should_prerender", "true");
+    return match;
+  }
+
+  GURL GetUrl(const std::string& path) { return test_server_.GetURL(path); }
+
   PrerenderManager* prerender_manager() { return prerender_manager_; }
 
   content::test::PrerenderTestHelper& prerender_helper() {
@@ -61,58 +83,63 @@
   raw_ptr<PrerenderManager> prerender_manager_;
 };
 
-TEST_F(PrerenderManagerTest, StartCleanPrerender) {
-  GURL prerendering_url = GetUrl("/title1.html");
+TEST_F(PrerenderManagerTest, StartCleanSearchSuggestionPrerender) {
+  GURL prerendering_url =
+      GetSearchSuggestionUrl("/title1.html", "pre", "prerender");
   content::test::PrerenderHostRegistryObserver registry_observer(
       *GetActiveWebContents());
-
-  prerender_manager()->Start(
-      prerendering_url, PrerenderManager::TriggerReason::kSearchSuggestion);
+  AutocompleteMatch match =
+      CreateSearchSuggestionMatch("/title1.html", "pre", "prerender");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
   registry_observer.WaitForTrigger(prerendering_url);
   int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url);
   EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
 }
 
 // Tests that the old prerender will be destroyed when starting prerendering a
-// different url.
-TEST_F(PrerenderManagerTest, StartNewPrerender) {
-  GURL prerendering_url = GetUrl("/title1.html");
+// different search result.
+TEST_F(PrerenderManagerTest, StartNewSuggestionPrerender) {
+  GURL prerendering_url =
+      GetSearchSuggestionUrl("/title1.html", "pre", "prefetch");
   content::test::PrerenderHostRegistryObserver registry_observer(
       *GetActiveWebContents());
+  AutocompleteMatch match =
+      CreateSearchSuggestionMatch("/title1.html", "pre", "prefetch");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
 
-  prerender_manager()->Start(
-      prerendering_url, PrerenderManager::TriggerReason::kSearchSuggestion);
   registry_observer.WaitForTrigger(prerendering_url);
   int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url);
   ASSERT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
   content::test::PrerenderHostObserver host_observer(*GetActiveWebContents(),
                                                      prerender_host_id);
-  GURL prerendering_url2 = GetUrl("/title2.html");
-  prerender_manager()->Start(
-      prerendering_url2, PrerenderManager::TriggerReason::kSearchSuggestion);
+  GURL prerendering_url2 =
+      GetSearchSuggestionUrl("/title1.html", "prer", "prerender");
+  match = CreateSearchSuggestionMatch("/title1.html", "prer", "prerender");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
   host_observer.WaitForDestroyed();
   registry_observer.WaitForTrigger(prerendering_url2);
-  EXPECT_TRUE(prerender_manager()->prerender_handle_for_testing());
+  EXPECT_TRUE(prerender_manager()->search_prerender_handle_for_testing());
   EXPECT_EQ(prerendering_url2, prerender_manager()
-                                   ->prerender_handle_for_testing()
+                                   ->search_prerender_handle_for_testing()
                                    ->GetInitialPrerenderingUrl());
 }
 
 // Tests that the old prerender is not destroyed when starting prerendering the
-// same url.
-TEST_F(PrerenderManagerTest, StartSamePrerender) {
-  GURL prerendering_url = GetUrl("/title1.html");
+// same search suggestion.
+TEST_F(PrerenderManagerTest, StartSameSuggestionPrerender) {
+  GURL prerendering_url =
+      GetSearchSuggestionUrl("/title1.html", "pre", "prerender");
   content::test::PrerenderHostRegistryObserver registry_observer(
       *GetActiveWebContents());
-
-  prerender_manager()->Start(
-      prerendering_url, PrerenderManager::TriggerReason::kSearchSuggestion);
+  AutocompleteMatch match =
+      CreateSearchSuggestionMatch("/title1.html", "pre", "prerender");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
   registry_observer.WaitForTrigger(prerendering_url);
   int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url);
   EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
-  prerender_manager()->Start(
-      prerendering_url, PrerenderManager::TriggerReason::kSearchSuggestion);
-  EXPECT_TRUE(prerender_manager()->prerender_handle_for_testing());
+  match = CreateSearchSuggestionMatch("/title1.html", "prer", "prerender");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
+  EXPECT_TRUE(prerender_manager()->search_prerender_handle_for_testing());
 
   // The created prerender for `prerendering_url` still exists, so the
   // prerender_host_id should be the same.
@@ -122,13 +149,14 @@
 
 // Tests that the PrerenderHandle is destroyed when the primary page changed.
 TEST_F(PrerenderManagerTest, DestroyedOnNavigateAway) {
-  web_contents_tester()->NavigateAndCommit(GetUrl("/empty.html"));
-  GURL prerendering_url = GetUrl("/title1.html");
+  GURL prerendering_url =
+      GetSearchSuggestionUrl("/title1.html", "pre", "prerende");
   content::test::PrerenderHostRegistryObserver registry_observer(
       *GetActiveWebContents());
+  AutocompleteMatch match =
+      CreateSearchSuggestionMatch("/title1.html", "pre", "prerende");
+  prerender_manager()->StartPrerenderAutocompleteMatch(match);
 
-  prerender_manager()->Start(
-      prerendering_url, PrerenderManager::TriggerReason::kSearchSuggestion);
   registry_observer.WaitForTrigger(prerendering_url);
   int prerender_host_id = prerender_helper().GetHostForUrl(prerendering_url);
   EXPECT_NE(prerender_host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
@@ -136,7 +164,7 @@
                                                      prerender_host_id);
   web_contents_tester()->NavigateAndCommit(GetUrl("/empty.html"));
   host_observer.WaitForDestroyed();
-  EXPECT_FALSE(prerender_manager()->prerender_handle_for_testing());
+  EXPECT_FALSE(prerender_manager()->search_prerender_handle_for_testing());
 }
 
 }  // namespace
diff --git a/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc b/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
index 4719742..4d20b543 100644
--- a/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
+++ b/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
@@ -96,10 +96,11 @@
   }
 
   void SelectAutocompleteMatchAndWaitForActivation(
-      const AutocompleteMatch& match) {
+      const AutocompleteMatch& match,
+      int host_id) {
     GURL url = match.destination_url;
     content::test::PrerenderHostObserver prerender_observer(
-        *GetActiveWebContents(), match.destination_url);
+        *GetActiveWebContents(), host_id);
     omnibox()->model()->OpenMatch(match, WindowOpenDisposition::CURRENT_TAB,
                                   url, std::u16string(), 0);
     prerender_observer.WaitForActivation();
@@ -357,7 +358,9 @@
     data.SetShortName(kSearchDomain16);
     data.SetKeyword(data.short_name());
     data.SetURL(search_engine_server_
-                    .GetURL(kSearchDomain, "/search_page.html?q={searchTerms}")
+                    .GetURL(kSearchDomain,
+                            "/search_page.html?q={searchTerms}&{google:"
+                            "originalQueryForSuggestion}")
                     .spec());
     data.suggestions_url =
         search_suggest_server_.GetURL(kSuggestDomain, "/?q={searchTerms}")
@@ -375,10 +378,8 @@
   std::unique_ptr<net::test_server::HttpResponse> HandleSearchSuggestRequest(
       const net::test_server::HttpRequest& request) {
     std::string content = "";
-    if (request.GetURL().spec().find("prerender2") != std::string::npos) {
-      content = R"([
-      "prerender2",
-      ["prerender222","prerender233"],
+    std::string hints = R"(
+      ["prerender222","prerender223"],
       ["", ""],
       [],
       {
@@ -386,6 +387,11 @@
           "pre": 0
         }
       }])";
+    if (request.GetURL().spec().find("prerender22") != std::string::npos) {
+      content = "[\"prerender22\"," + hints;
+    } else if (request.GetURL().spec().find("prerender2") !=
+               std::string::npos) {
+      content = "[\"prerender2\"," + hints;
     }
     auto resp = std::make_unique<net::test_server::BasicHttpResponse>();
     resp->set_code(net::HTTP_OK);
@@ -408,9 +414,10 @@
     return resp;
   }
 
-  GURL GetSearchUrl(std::string key_word) {
-    return search_engine_server_.GetURL(kSearchDomain,
-                                        "/search_page.html?q=" + key_word);
+  GURL GetSearchUrl(const std::string& query, std::string search_terms) {
+    return search_engine_server_.GetURL(
+        kSearchDomain,
+        "/search_page.html?q=" + search_terms + "&oq=" + query + "&");
   }
 
   AutocompleteController* GetAutocompleteController() {
@@ -434,19 +441,20 @@
 // Tests the basic functionality of prerendering a search suggestion with search
 // suggestion hints.
 IN_PROC_BROWSER_TEST_F(PrerenderOmniboxSearchSuggestionUIBrowserTest,
-                       SearchPrerenderSeggestion) {
+                       SearchPrerenderSuggestion) {
   const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
   ASSERT_TRUE(GetActiveWebContents());
   ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), kInitialUrl));
   Observe(GetActiveWebContents());
-  std::string search_terms = "prerender2";
-  GURL prerender_url = GetSearchUrl("prerender222");
+  std::string search_query = "prerender2";
+  GURL prerender_url = GetSearchUrl(search_query, "prerender222");
+
   content::test::PrerenderHostRegistryObserver registry_observer(
       *GetActiveWebContents());
 
   // Trigger an omnibox suggest that has a prerender hint.
   AutocompleteInput input(
-      base::ASCIIToUTF16(search_terms), metrics::OmniboxEventProto::BLANK,
+      base::ASCIIToUTF16(search_query), metrics::OmniboxEventProto::BLANK,
       ChromeAutocompleteSchemeClassifier(chrome_test_utils::GetProfile(this)));
   AutocompleteController* autocomplete_controller = GetAutocompleteController();
 
@@ -456,6 +464,8 @@
 
   // The suggestion service should hint a prerender_url.
   registry_observer.WaitForTrigger(prerender_url);
+  int host_id = prerender_helper().GetHostForUrl(prerender_url);
+  ASSERT_NE(host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
 
   // Ensure there is a search hint.
   auto is_prerender_match = [](const AutocompleteMatch& match) {
@@ -466,7 +476,55 @@
       std::end(autocomplete_controller->result()), is_prerender_match);
   ASSERT_NE(prerender_match, std::end(autocomplete_controller->result()));
 
-  SelectAutocompleteMatchAndWaitForActivation(*prerender_match);
+  SelectAutocompleteMatchAndWaitForActivation(*prerender_match, host_id);
+  EXPECT_TRUE(IsPrerenderingNavigation());
+  EXPECT_EQ(GetActiveWebContents()->GetLastCommittedURL(), prerender_url);
+}
+
+// Test that prerender maintain the previous prerendered page if the new
+// prerendering aims to load a same url to the prerendered page.
+IN_PROC_BROWSER_TEST_F(PrerenderOmniboxSearchSuggestionUIBrowserTest,
+                       SameSuggestion) {
+  const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
+  ASSERT_TRUE(GetActiveWebContents());
+  ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), kInitialUrl));
+  Observe(GetActiveWebContents());
+  std::string search_query_1 = "prerender2";
+  GURL prerender_url = GetSearchUrl(search_query_1, "prerender222");
+
+  content::test::PrerenderHostRegistryObserver registry_observer(
+      *GetActiveWebContents());
+
+  // Trigger an omnibox suggest that has a prerender hint.
+  AutocompleteInput input(
+      base::ASCIIToUTF16(search_query_1), metrics::OmniboxEventProto::BLANK,
+      ChromeAutocompleteSchemeClassifier(chrome_test_utils::GetProfile(this)));
+  AutocompleteController* autocomplete_controller = GetAutocompleteController();
+
+  // After receiving `input`, the controller should ask suggestion service for
+  // search suggestion.
+  autocomplete_controller->Start(input);
+
+  // The suggestion service should hint a prerender_url.
+  registry_observer.WaitForTrigger(prerender_url);
+  int host_id = prerender_helper().GetHostForUrl(prerender_url);
+  ASSERT_NE(host_id, content::RenderFrameHost::kNoFrameTreeNodeId);
+
+  std::string search_query_2 = "prerender22";
+  AutocompleteInput input2(
+      base::ASCIIToUTF16(search_query_2), metrics::OmniboxEventProto::BLANK,
+      ChromeAutocompleteSchemeClassifier(chrome_test_utils::GetProfile(this)));
+  autocomplete_controller->Start(input2);
+  base::RunLoop().RunUntilIdle();
+  // Ensure there is a search hint.
+  auto is_prerender_match = [](const AutocompleteMatch& match) {
+    return BaseSearchProvider::ShouldPrerender(match);
+  };
+  auto prerender_match = std::find_if(
+      std::begin(autocomplete_controller->result()),
+      std::end(autocomplete_controller->result()), is_prerender_match);
+  ASSERT_NE(prerender_match, std::end(autocomplete_controller->result()));
+  SelectAutocompleteMatchAndWaitForActivation(*prerender_match, host_id);
   EXPECT_TRUE(IsPrerenderingNavigation());
   EXPECT_EQ(GetActiveWebContents()->GetLastCommittedURL(), prerender_url);
 }
diff --git a/chrome/browser/privacy_sandbox/android/java/res/xml/privacy_sandbox_preferences_v3.xml b/chrome/browser/privacy_sandbox/android/java/res/xml/privacy_sandbox_preferences_v3.xml
index d3a25d0..80027e7 100644
--- a/chrome/browser/privacy_sandbox/android/java/res/xml/privacy_sandbox_preferences_v3.xml
+++ b/chrome/browser/privacy_sandbox/android/java/res/xml/privacy_sandbox_preferences_v3.xml
@@ -23,21 +23,18 @@
         android:fragment="org.chromium.chrome.browser.privacy_sandbox.AdPersonalizationFragment"
         android:title="@string/privacy_sandbox_ad_personalization_title"
         android:summary="@string/privacy_sandbox_ad_personalization_summary"
-        android:icon="@drawable/permission_cookie"
-        app:iconTint="@macro/default_icon_color" />
+        android:icon="@drawable/gm_ads_click_24"/>
 
     <org.chromium.components.browser_ui.settings.ChromeBasePreference
         android:fragment="org.chromium.chrome.browser.privacy_sandbox.AdMeasurementFragment"
         android:title="@string/privacy_sandbox_ad_measurement_title"
         android:summary="@string/privacy_sandbox_ad_measurement_summary"
-        android:icon="@drawable/permission_cookie"
-        app:iconTint="@macro/default_icon_color" />
+        android:icon="@drawable/gm_insert_chart_24"/>
 
     <org.chromium.components.browser_ui.settings.ChromeBasePreference
         android:fragment="org.chromium.chrome.browser.privacy_sandbox.SpamFraudFragment"
         android:title="@string/privacy_sandbox_spam_fraud_title"
         android:summary="@string/privacy_sandbox_spam_fraud_summary"
-        android:icon="@drawable/permission_cookie"
-        app:iconTint="@macro/default_icon_color" />
+        android:icon="@drawable/ic_spam_reduction_24dp" />
 
 </PreferenceScreen>
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationFragment.java
index fbb9a8c..663579e 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationFragment.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationFragment.java
@@ -15,6 +15,8 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 
+import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.browser_ui.settings.ImageButtonPreference;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 
@@ -29,10 +31,16 @@
     private static final String EMPTY_TOPICS_PREFERENCE = "empty_topics";
     private static final String REMOVE_TOPICS_PREFERENCE = "removed_topics";
 
+    private SnackbarManager mSnackbarManager;
+
     private PreferenceCategory mTopicsCategory;
     private Preference mEmptyTopicsPreference;
     private Preference mRemoveTopicsPreference;
 
+    public void setSnackbarManager(SnackbarManager snackbarManager) {
+        mSnackbarManager = snackbarManager;
+    }
+
     /**
      * Initializes all the objects related to the preferences page.
      */
@@ -91,6 +99,9 @@
         if (preference instanceof ImageButtonPreference) {
             blockTopic(preference.getTitle().toString());
             mTopicsCategory.removePreference(preference);
+            mSnackbarManager.showSnackbar(Snackbar.make(
+                    getResources().getString(R.string.privacy_sandbox_remove_interest_snackbar),
+                    null, Snackbar.TYPE_ACTION, Snackbar.UMA_PRIVACY_SANDBOX_REMOVE_INTEREST));
         }
         return true;
     }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationRemovedFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationRemovedFragment.java
index 79f45d0..47f7eb9 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationRemovedFragment.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationRemovedFragment.java
@@ -15,11 +15,11 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 
+import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.browser_ui.settings.ImageButtonPreference;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 
-import java.util.List;
-
 /**
  * Settings fragment for privacy sandbox settings.
  */
@@ -28,6 +28,11 @@
     private static final String TOPICS_CATEGORY_PREFERENCE = "topic_interests";
 
     private PreferenceCategory mTopicsCategory;
+    private SnackbarManager mSnackbarManager;
+
+    public void setSnackbarManager(SnackbarManager snackbarManager) {
+        mSnackbarManager = snackbarManager;
+    }
 
     /**
      * Initializes all the objects related to the preferences page.
@@ -40,7 +45,7 @@
         mTopicsCategory = findPreference(TOPICS_CATEGORY_PREFERENCE);
         assert mTopicsCategory != null;
 
-        for (String interest : getBlockedTopics()) {
+        for (String interest : PrivacySandboxBridge.getBlockedTopics()) {
             ImageButtonPreference interestPreference = new ImageButtonPreference(getContext());
             interestPreference.setTitle(interest);
             interestPreference.setImage(
@@ -60,10 +65,6 @@
         return view;
     }
 
-    private List<String> getBlockedTopics() {
-        return PrivacySandboxBridge.getBlockedTopics();
-    }
-
     private void allowTopic(String topic) {
         PrivacySandboxBridge.setTopicAllowed(topic, true);
     }
@@ -73,6 +74,9 @@
         if (preference instanceof ImageButtonPreference) {
             allowTopic(preference.getTitle().toString());
             mTopicsCategory.removePreference(preference);
+            mSnackbarManager.showSnackbar(Snackbar.make(
+                    getResources().getString(R.string.privacy_sandbox_add_interest_snackbar), null,
+                    Snackbar.TYPE_ACTION, Snackbar.UMA_PRIVACY_SANDBOX_ADD_INTEREST));
         }
         return true;
     }
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 221c80d..906bc4d 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
@@ -159,6 +159,8 @@
         clickImageButtonNextToText("Foo");
         assertThat(PrivacySandboxBridge.getCurrentTopTopics(), not(hasItem("Foo")));
         assertThat(PrivacySandboxBridge.getBlockedTopics(), hasItem("Foo"));
+        onView(withText(R.string.privacy_sandbox_remove_interest_snackbar))
+                .check(matches(isDisplayed()));
     }
 
     @Test
@@ -182,6 +184,8 @@
         clickImageButtonNextToText("BlockedFoo");
         assertThat(PrivacySandboxBridge.getCurrentTopTopics(), hasItem("BlockedFoo"));
         assertThat(PrivacySandboxBridge.getBlockedTopics(), not(hasItem("BlockedFoo")));
+        onView(withText(R.string.privacy_sandbox_add_interest_snackbar))
+                .check(matches(isDisplayed()));
     }
 
     @Test
diff --git a/chrome/browser/resources/feedback_webui/css/feedback.css b/chrome/browser/resources/feedback_webui/css/feedback.css
index c3636b2..08dab03 100644
--- a/chrome/browser/resources/feedback_webui/css/feedback.css
+++ b/chrome/browser/resources/feedback_webui/css/feedback.css
@@ -79,6 +79,16 @@
   padding-inline-start: 10px;
 }
 
+:is(input, select, textarea) {
+  background-color: var(--feedback-textfield-bg-color);
+}
+
+:is(input, select, textarea):active,
+:is(input, select, textarea):focus {
+  caret-color: var(--feedback-prominent-color);
+  outline: 2px solid var(--feedback-focus-color);
+}
+
 .content .text-field-container > label {
   flex: 0 1 auto;
   width: 100px;
@@ -86,7 +96,7 @@
 
 .content .text-field-container > select {
   border: 1px solid var(--feedback-separator-color);
-  color: var(--feedback-secondary-color);
+  color: var(--feedback-primary-color);
   flex: 1 1 auto;
   height: 100%;
   padding-inline-start: 5px;
@@ -101,6 +111,10 @@
   padding-inline-start: 5px;
 }
 
+.content .text-field-container > input:focus {
+  color: var(--feedback-primary-color);
+}
+
 .content .text-field-container > input[type=checkbox] {
   margin-inline-end: 9px;
 }
@@ -250,3 +264,10 @@
   top: auto;
   width: 1px;
 }
+
+option {
+  background: var(--feedback-bg-color) linear-gradient(
+      rgba(255,255,255, 0.06),rgba(255,255,255, 0.06));
+  box-shadow: 0 1px 2px rgba(var(--feedback-box-shadow-color), 0.3),
+              0 1px 6px rgba(var(--feedback-box-shadow-color), 0.15);
+}
diff --git a/chrome/browser/resources/feedback_webui/css/feedback_shared_styles.css b/chrome/browser/resources/feedback_webui/css/feedback_shared_styles.css
index 885d6d9b..9582bc0 100644
--- a/chrome/browser/resources/feedback_webui/css/feedback_shared_styles.css
+++ b/chrome/browser/resources/feedback_webui/css/feedback_shared_styles.css
@@ -13,3 +13,39 @@
 a[href] {
   color: var(--feedback-link-color);
 }
+
+a[href]:focus,
+button.blue-button:focus,
+button.white-button:focus {
+  outline: 2px solid var(--feedback-focus-color);
+  outline-offset: 2px;
+}
+
+@media (prefers-color-scheme: dark) {
+  button.blue-button,
+  button.white-button {
+    outline-width: 0;
+  }
+
+  button.blue-button {
+    background-color: var(--feedback-prominent-color);
+    border: none;
+    color: var(--google-grey-900);
+  }
+
+  button.blue-button:hover {
+    background: var(--feedback-prominent-color) linear-gradient(
+        rgba(0, 0, 0, 0.08),
+        rgba(0, 0, 0, 0.08));
+  }
+
+  button.white-button {
+    background-color: var(--feedback-bg-color);
+    border-color: var(--google-grey-700);
+    color: var(--feedback-prominent-color);
+  }
+
+  button.white-button:hover {
+    background-color: rgba(var(--google-blue-300-rgb), 0.08);
+  }
+}
diff --git a/chrome/browser/resources/feedback_webui/css/feedback_shared_vars.css b/chrome/browser/resources/feedback_webui/css/feedback_shared_vars.css
index a8a9583..c6328cd 100644
--- a/chrome/browser/resources/feedback_webui/css/feedback_shared_vars.css
+++ b/chrome/browser/resources/feedback_webui/css/feedback_shared_vars.css
@@ -9,6 +9,7 @@
   --google-blue-300: rgb(var(--google-blue-300-rgb));
   --google-blue-600: rgb(26, 115, 232);
 
+  --google-grey-100: rgb(241, 243, 244);
   --google-grey-200: rgb(232, 234, 237);
   --google-grey-500: rgb(154, 160, 166);
   --google-grey-700: rgb(95, 99, 104);
@@ -21,13 +22,15 @@
   /* Feedback specific variables. */
   --feedback-alert-color: var(--google-red-600);
   --feedback-bg-color: rgb(255, 255, 255);
-  --feedback-box-shadow-color: #d0d0d0;
+  --feedback-box-shadow-color: rgb(208, 208, 208);
+  --feedback-focus-color: var(--google-blue-600);
   --feedback-highlight-color: var(--google-blue-50);
   --feedback-link-color: var(--google-blue-600);
   --feedback-primary-color: var(--google-grey-900);
   --feedback-prominent-color: var(--google-blue-600);
   --feedback-secondary-color: var(--google-grey-700);
   --feedback-separator-color: rgba(0, 0, 0, 0.14);
+  --feedback-textfield-bg-color: var(--google-grey-100);
 }
 
 @media (prefers-color-scheme: dark) {
@@ -35,11 +38,13 @@
     --feedback-alert-color: var(--google-red-300);
     --feedback-bg-color: var(--google-grey-900);
     --feedback-box-shadow-color: rgba(var(--google-grey-900-rgb), 0.04);
+    --feedback-focus-color: var(--google-blue-300);
     --feedback-highlight-color: rgba(var(--google-blue-300-rgb), 0.3);
     --feedback-link-color: var(--google-blue-300);
     --feedback-primary-color: var(--google-grey-200);
     --feedback-prominent-color: var(--google-blue-300);
     --feedback-secondary-color: var(--google-grey-500);
     --feedback-separator-color: rgba(255, 255, 255, 0.14);
+    --feedback-textfield-bg-color: rgba(0,0,0,0.3);
   }
 }
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn
index 11c1e16..56248706 100644
--- a/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -387,11 +387,11 @@
                "metrics_utils.js",
                "middle_slot_promo.ts",
                "mini_page.ts",
-               "modules/cart/chrome_cart_proxy.js",
-               "modules/cart/module.js",
+               "modules/cart/chrome_cart_proxy.ts",
+               "modules/cart/module.ts",
                "modules/cart_v2/module.ts",
-               "modules/drive/drive_module_proxy.js",
-               "modules/drive/module.js",
+               "modules/drive/drive_module_proxy.ts",
+               "modules/drive/module.ts",
                "modules/drive_v2/module.ts",
                "modules/info_dialog.js",
                "modules/module_descriptor.js",
@@ -400,11 +400,11 @@
                "modules/module_registry.js",
                "modules/modules.js",
                "modules/module_wrapper.js",
-               "modules/photos/module.js",
-               "modules/photos/photos_module_proxy.js",
+               "modules/photos/module.ts",
+               "modules/photos/photos_module_proxy.ts",
                "modules/recipes_v2/module.ts",
-               "modules/task_module/module.js",
-               "modules/task_module/task_module_handler_proxy.js",
+               "modules/task_module/module.ts",
+               "modules/task_module/task_module_handler_proxy.ts",
                "new_tab_page.js",
                "new_tab_page_proxy.js",
                "realbox/realbox_action.ts",
diff --git a/chrome/browser/resources/new_tab_page/customize_backgrounds.ts b/chrome/browser/resources/new_tab_page/customize_backgrounds.ts
index ebb1281..7995a68 100644
--- a/chrome/browser/resources/new_tab_page/customize_backgrounds.ts
+++ b/chrome/browser/resources/new_tab_page/customize_backgrounds.ts
@@ -7,12 +7,11 @@
 import './mini_page.js';
 import './iframe.js';
 
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {I18nMixin, loadTimeData} from './i18n_setup.js';
 import {BackgroundCollection, CollectionImage, CustomizeDialogAction, PageHandlerRemote, Theme} from './new_tab_page.mojom-webui.js';
 import {NewTabPageProxy} from './new_tab_page_proxy.js';
-import {RepeaterEvent} from './utils_ts.js';
 
 /** Element that lets the user configure the background. */
 export class CustomizeBackgroundsElement extends I18nMixin
@@ -98,7 +97,7 @@
         '';
   }
 
-  private onCollectionClick_(e: RepeaterEvent<BackgroundCollection>) {
+  private onCollectionClick_(e: DomRepeatEvent<BackgroundCollection>) {
     this.selectedCollection = e.model.item;
     this.pageHandler_.onCustomizeDialogAction(
         CustomizeDialogAction.kBackgroundsCollectionOpened);
@@ -123,7 +122,7 @@
     this.pageHandler_.setNoBackgroundImage();
   }
 
-  private onImageClick_(e: RepeaterEvent<CollectionImage>) {
+  private onImageClick_(e: DomRepeatEvent<CollectionImage>) {
     const image = e.model.item;
     if (this.theme.isCustomBackground &&
         this.theme.backgroundImage!.url.url !== image.imageUrl.url) {
diff --git a/chrome/browser/resources/new_tab_page/modules/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
index 0863189..1831aca8 100644
--- a/chrome/browser/resources/new_tab_page/modules/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/BUILD.gn
@@ -36,10 +36,6 @@
   deps = [
     ":module_descriptor",
     "..:i18n_setup",
-    "cart:module",
-    "drive:module",
-    "photos:module",
-    "task_module:module",
     "//ui/webui/resources/js:load_time_data.m",
   ]
   if (!is_official_build) {
@@ -62,6 +58,7 @@
   deps = [
     "..:i18n_setup",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
   ]
 }
 
@@ -118,10 +115,10 @@
     "module_descriptor.js",
     "module_descriptors.js",
     "module_registry.js",
-    "task_module/task_module_handler_proxy.js",
-    "cart/chrome_cart_proxy.js",
-    "drive/drive_module_proxy.js",
-    "photos/photos_module_proxy.js",
+    "task_module/task_module_handler_proxy.ts",
+    "cart/chrome_cart_proxy.ts",
+    "drive/drive_module_proxy.ts",
+    "photos/photos_module_proxy.ts",
   ]
   if (!is_official_build) {
     in_files += [ "dummy_v2/foo_proxy.js" ]
@@ -138,13 +135,13 @@
     "module_wrapper.js",
     "modules.js",
     "info_dialog.js",
-    "task_module/module.js",
+    "task_module/module.ts",
     "recipes_v2/module.ts",
-    "cart/module.js",
+    "cart/module.ts",
     "cart_v2/module.ts",
-    "drive/module.js",
+    "drive/module.ts",
     "drive_v2/module.ts",
-    "photos/module.js",
+    "photos/module.ts",
   ]
   if (!is_official_build) {
     in_files += [ "dummy_v2/module.js" ]
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/cart/BUILD.gn
index d85dfe99..5f76427 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/cart/BUILD.gn
@@ -2,27 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
-js_library("module") {
-  deps = [
-    ":chrome_cart_proxy",
-    "..:module_descriptor",
-    "../..:i18n_setup",
-    "//chrome/browser/cart:mojo_bindings_webui_js",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
-    "//ui/webui/resources/cr_elements/cr_auto_img",
-    "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
-    "//ui/webui/resources/cr_elements/cr_toast:cr_toast",
-  ]
-}
-
-js_library("chrome_cart_proxy") {
-  deps = [ "//chrome/browser/cart:mojo_bindings_webui_js" ]
-}
-
 html_to_js("web_components") {
-  js_files = [ "module.js" ]
+  js_files = [ "module.ts" ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.js b/chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.ts
similarity index 71%
rename from chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.js
rename to chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.ts
index 066cbbc..318073b 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.js
+++ b/chrome/browser/resources/new_tab_page/modules/cart/chrome_cart_proxy.ts
@@ -10,20 +10,16 @@
  * browser and receiving the browser response.
  */
 
-/** @type {?CartHandlerRemote} */
-let handler = null;
+let handler: CartHandlerRemote|null = null;
 
 export class ChromeCartProxy {
-  /** @return {!CartHandlerRemote} */
-  static getHandler() {
+  static getHandler(): CartHandlerRemote {
     return handler || (handler = CartHandler.getRemote());
   }
 
-  /** @param {!CartHandlerRemote} newHandler */
-  static setHandler(newHandler) {
+  static setHandler(newHandler: CartHandlerRemote) {
     handler = newHandler;
   }
 
-  /** @private */
-  constructor() {}
+  private constructor() {}
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/module.js b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
similarity index 76%
rename from chrome/browser/resources/new_tab_page/modules/cart/module.js
rename to chrome/browser/resources/new_tab_page/modules/cart/module.ts
index c1f7f96..7ce1119 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
@@ -10,90 +10,80 @@
 import 'chrome://resources/cr_elements/cr_auto_img/cr_auto_img.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
+import {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
+import {DomRepeat, DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MerchantCart} from '../../chrome_cart.mojom-webui.js';
-import {I18nBehavior, loadTimeData} from '../../i18n_setup.js';
+import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
 import {recordOccurence} from '../../metrics_utils.js';
 import {$$} from '../../utils.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
 import {ChromeCartProxy} from './chrome_cart_proxy.js';
 
+interface ChromeCartModuleElement {
+  $: {
+    cartActionMenu: CrActionMenuElement,
+    cartCarousel: HTMLElement,
+    cartItemRepeat: DomRepeat,
+    confirmDiscountConsentToast: CrToastElement,
+    dismissCartToast: CrToastElement,
+  };
+}
+
 /**
  * Implements the UI of chrome cart module. This module shows pending carts for
  * users on merchant sites so that users can resume shopping journey.
- * @polymer
- * @extends {PolymerElement}
  */
-class ChromeCartModuleElement extends mixinBehaviors
-([I18nBehavior], PolymerElement) {
+class ChromeCartModuleElement extends I18nMixin
+(PolymerElement) {
   static get is() {
     return 'ntp-chrome-cart-module';
   }
 
-  static get template() {
-    return html`{__html_template__}`;
-  }
-
   static get properties() {
     return {
-      /** @type {!Array<!MerchantCart>} */
       cartItems: Array,
-
-      /** @type {string} */
       headerChipText: String,
 
-      /** @type {string} */
       headerDescriptionText: {
         type: String,
         reflectToAttribute: true,
       },
 
-      /** @type {boolean} */
       showDiscountConsent: Boolean,
-
-      /** @private {boolean} */
       showLeftScrollButton_: Boolean,
-
-      /** @private {boolean} */
       showRightScrollButton_: Boolean,
-
-      /** @private {string} */
       cartMenuHideItem_: String,
-
-      /** @private {string} */
       cartMenuRemoveItem_: String,
 
-      /**
-       * Data about the most recently dismissed cart item.
-       * @type {?{message: string, restoreCallback: function()}}
-       * @private
-       */
+      /** Data about the most recently dismissed cart item. */
       dismissedCartData_: {
         type: Object,
         value: null,
       },
 
-      /** @private {string} */
       confirmDiscountConsentString_: String,
     };
   }
 
-  constructor() {
-    super();
+  cartItems: MerchantCart[];
+  headerChipText: string;
+  headerDescriptionText: string;
+  showDiscountConsent: boolean;
+  scrollBehavior: ScrollBehavior = 'smooth';
+  private showLeftScrollButton_: boolean;
+  private showRightScrollButton_: boolean;
+  private cartMenuHideItem_: string;
+  private cartMenuRemoveItem_: string;
+  private dismissedCartData_: {message: string, restoreCallback: () => void}|
+      null;
+  private confirmDiscountConsentString_: string;
 
-    /** @private {IntersectionObserver} */
-    this.intersectionObserver_ = null;
+  private intersectionObserver_: IntersectionObserver|null = null;
+  private currentMenuIndex_: number = 0;
 
-    /** @type {string} */
-    this.scrollBehavior = 'smooth';
-
-    /** @private {number} */
-    this.currentMenuIndex_ = 0;
-  }
-
-  /** @override */
   connectedCallback() {
     super.connectedCallback();
     const leftProbe = this.$.cartCarousel.querySelector('#leftProbe');
@@ -118,22 +108,16 @@
         }
       });
     }, {root: this.$.cartCarousel});
-    this.shadowRoot.querySelectorAll('.probe').forEach(
-        el => this.intersectionObserver_.observe(el));
+    this.shadowRoot!.querySelectorAll('.probe').forEach(
+        el => this.intersectionObserver_!.observe(el));
   }
 
-  /** @override */
   disconnectedCallback() {
     super.disconnectedCallback();
-    this.intersectionObserver_.disconnect();
+    this.intersectionObserver_!.disconnect();
   }
 
-  /**
-   * @param {string} url
-   * @return {string}
-   * @private
-   */
-  getFaviconUrl_(url) {
+  private getFaviconUrl_(url: string): string {
     const faviconUrl = new URL('chrome://favicon2/');
     faviconUrl.searchParams.set('size', '24');
     faviconUrl.searchParams.set('scale_factor', '1x');
@@ -142,34 +126,23 @@
     return faviconUrl.href;
   }
 
-  /**
-   * @param {!Array<string>} imageUrls
-   * @return {!Array<string>}
-   * @private
-   */
-  getImagesToShow_(imageUrls) {
+  private getImagesToShow_(imageUrls: string[]): string[] {
     return imageUrls.slice(0, 3);
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onCartMenuButtonClick_(e) {
+  private onCartMenuButtonClick_(e: DomRepeatEvent<MerchantCart>) {
     e.preventDefault();
     e.stopPropagation();
-    this.currentMenuIndex_ =
-        this.$.cartItemRepeat.indexForElement(e.target.parentElement);
+    this.currentMenuIndex_ = e.model.index;
     const merchant = this.cartItems[this.currentMenuIndex_].merchant;
     this.cartMenuHideItem_ =
         loadTimeData.getStringF('modulesCartCartMenuHideMerchant', merchant);
     this.cartMenuRemoveItem_ =
         loadTimeData.getStringF('modulesCartCartMenuRemoveMerchant', merchant);
-    this.$.cartActionMenu.showAt(e.target);
+    this.$.cartActionMenu.showAt(e.target as HTMLElement);
   }
 
-  /** @private */
-  async onCartHide_() {
+  private async onCartHide_() {
     this.$.cartActionMenu.close();
     const merchant = this.cartItems[this.currentMenuIndex_].merchant;
     const cartUrl = this.cartItems[this.currentMenuIndex_].cartUrl;
@@ -185,12 +158,11 @@
     };
     const isModuleVisible = await this.resetCartData_();
     if (isModuleVisible) {
-      $$(this, '#dismissCartToast').show();
+      this.$.dismissCartToast.show();
     }
   }
 
-  /** @private */
-  async onCartRemove_() {
+  private async onCartRemove_() {
     this.$.cartActionMenu.close();
     const merchant = this.cartItems[this.currentMenuIndex_].merchant;
     const cartUrl = this.cartItems[this.currentMenuIndex_].cartUrl;
@@ -206,26 +178,22 @@
     };
     const isModuleVisible = await this.resetCartData_();
     if (isModuleVisible) {
-      $$(this, '#dismissCartToast').show();
+      this.$.dismissCartToast.show();
     }
   }
 
-  /** @private */
-  async onUndoDismissCartButtonClick_() {
+  private async onUndoDismissCartButtonClick_() {
     // Restore the module item.
-    await this.dismissedCartData_.restoreCallback();
+    await this.dismissedCartData_!.restoreCallback();
     this.dismissedCartData_ = null;
     this.resetCartData_();
 
     // Notify the user.
-    $$(this, '#dismissCartToast').hide();
+    this.$.dismissCartToast.hide();
   }
 
-  /**
-   * @return {!Promise<!boolean>} Whether the module is visible after reset.
-   * @private
-   */
-  async resetCartData_() {
+  /** @return Whether the module is visible after reset. */
+  private async resetCartData_(): Promise<boolean> {
     const {carts} = await ChromeCartProxy.getHandler().getMerchantCarts();
     this.cartItems = carts;
     const isModuleVisible = this.cartItems.length !== 0;
@@ -238,7 +206,7 @@
           restoreCallback: async () => {
             chrome.metricsPrivate.recordUserAction(
                 'NewTabPage.Carts.RestoreLastCartRestoresModule');
-            await this.dismissedCartData_.restoreCallback();
+            await this.dismissedCartData_!.restoreCallback();
             this.dismissedCartData_ = null;
             const {carts} =
                 await ChromeCartProxy.getHandler().getMerchantCarts();
@@ -252,8 +220,7 @@
     return isModuleVisible;
   }
 
-  /** @private */
-  onDismissButtonClick_() {
+  private onDismissButtonClick_() {
     ChromeCartProxy.getHandler().hideCartModule();
     this.dispatchEvent(new CustomEvent('dismiss-module', {
       bubbles: true,
@@ -271,8 +238,7 @@
     chrome.metricsPrivate.recordUserAction('NewTabPage.Carts.HideModule');
   }
 
-  /** @private */
-  onDisableButtonClick_() {
+  private onDisableButtonClick_() {
     this.dispatchEvent(new CustomEvent('disable-module', {
       bubbles: true,
       composed: true,
@@ -292,9 +258,8 @@
   /**
    * Gets called when the right scroll button is clicked to show the next items
    * on the right.
-   * @private
    */
-  onRightScrollClick_() {
+  private onRightScrollClick_() {
     const carts = this.$.cartCarousel.querySelectorAll('.cart-container');
     let lastVisibleIndex = 0;
     for (let i = 0; i < carts.length; i++) {
@@ -309,9 +274,8 @@
   /**
    * Gets called when the left scroll button is clicked to show the previous
    * items on the left.
-   * @private
    */
-  onLeftScrollClick_() {
+  private onLeftScrollClick_() {
     const carts = this.$.cartCarousel.querySelectorAll('.cart-container');
     let visibleRange = 0, firstVisibleIndex = 0;
     for (let i = carts.length - 1; i >= 0; i--) {
@@ -324,16 +288,15 @@
     chrome.metricsPrivate.recordUserAction('NewTabPage.Carts.LeftScrollClick');
   }
 
-  /**
-   * @param {!number} index The target index to scroll to.
-   * @private
-   */
-  scrollToIndex_(index) {
-    const carts = this.$.cartCarousel.querySelectorAll('.cart-container');
+  /** @param index The target index to scroll to. */
+  private scrollToIndex_(index: number) {
+    const carts =
+        this.$.cartCarousel.querySelectorAll<HTMLElement>('.cart-container');
     // Calculate scroll shadow width as scroll offset.
-    const leftScrollShadow = this.shadowRoot.getElementById('leftScrollShadow');
+    const leftScrollShadow =
+        this.shadowRoot!.getElementById('leftScrollShadow');
     const rightScrollShadow =
-        this.shadowRoot.getElementById('rightScrollShadow');
+        this.shadowRoot!.getElementById('rightScrollShadow');
     const scrollOffset = Math.max(
         leftScrollShadow ? leftScrollShadow.offsetWidth : 0,
         rightScrollShadow ? rightScrollShadow.offsetWidth : 0);
@@ -341,7 +304,7 @@
     // TODO(crbug.com/1198632): This could make a left scroll jump over cart
     // items.
     if (index === 0) {
-      const consentCard = this.shadowRoot.getElementById('consentCard');
+      const consentCard = this.shadowRoot!.getElementById('consentCard');
       if (consentCard) {
         leftPosition -= consentCard.offsetWidth;
       }
@@ -353,25 +316,19 @@
     });
   }
 
-  /**
-   * @param {!number} index
-   * @return {!boolean} True if the item at index is completely visible.
-   * @private
-   */
-  getVisibilityForIndex_(index) {
+  /** @return Whether the item at index is completely visible. */
+  private getVisibilityForIndex_(index: number): boolean {
     const cartCarousel = this.$.cartCarousel;
-    const cart = cartCarousel.querySelectorAll('.cart-container')[index];
+    const cart =
+        cartCarousel.querySelectorAll<HTMLElement>('.cart-container')[index];
     return cart && (cart.offsetLeft > cartCarousel.scrollLeft) &&
         (cartCarousel.scrollLeft + cartCarousel.clientWidth) >
         (cart.offsetLeft + cart.offsetWidth);
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  async onCartItemClick_(e) {
-    const index = this.$.cartItemRepeat.indexForElement(e.target);
+  private async onCartItemClick_(e: Event&{shouldNavigate?: boolean}) {
+    const index =
+        this.$.cartItemRepeat.indexForElement(e.target as HTMLElement)!;
     // When rule-based discount is enabled, clicking on the cart wouldn't
     // trigger navigation immediately. Instead, we'll fetch discount URL from
     // browser process and re-bind URL. Then, we create a new pointer event by
@@ -385,7 +342,7 @@
           this.cartItems[index].cartUrl);
       this.set(`cartItems.${index}.cartUrl`, discountUrl);
       const cloneEvent = new PointerEvent(e.type, e);
-      cloneEvent.shouldNavigate = true;
+      (cloneEvent as {shouldNavigate?: boolean}).shouldNavigate = true;
       this.$.cartCarousel.querySelectorAll('.cart-item')[index].dispatchEvent(
           cloneEvent);
       return;
@@ -396,45 +353,44 @@
     chrome.metricsPrivate.recordSmallCount('NewTabPage.Carts.ClickCart', index);
   }
 
-  /** @private */
-  onDisallowDiscount_() {
+  private onDisallowDiscount_() {
     this.showDiscountConsent = false;
     this.confirmDiscountConsentString_ =
         loadTimeData.getString('modulesCartDiscountConsentRejectConfirmation');
-    $$(this, '#confirmDiscountConsentToast').show();
+    this.$.confirmDiscountConsentToast.show();
     ChromeCartProxy.getHandler().onDiscountConsentAcknowledged(false);
     chrome.metricsPrivate.recordUserAction(
         'NewTabPage.Carts.RejectDiscountConsent');
   }
 
-  /** @private */
-  onAllowDiscount_() {
+  private onAllowDiscount_() {
     this.showDiscountConsent = false;
     this.confirmDiscountConsentString_ =
         loadTimeData.getString('modulesCartDiscountConsentAcceptConfirmation');
-    $$(this, '#confirmDiscountConsentToast').show();
+    this.$.confirmDiscountConsentToast.show();
     ChromeCartProxy.getHandler().onDiscountConsentAcknowledged(true);
     chrome.metricsPrivate.recordUserAction(
         'NewTabPage.Carts.AcceptDiscountConsent');
   }
 
-  /** @private */
-  onConfirmDiscountConsentClick_() {
-    $$(this, '#confirmDiscountConsentToast').hide();
+  private onConfirmDiscountConsentClick_() {
+    this.$.confirmDiscountConsentToast.hide();
   }
 
-  /** @private */
-  onCartItemContextMenuClick_(e) {
-    const index = this.$.cartItemRepeat.indexForElement(e.target);
+  private onCartItemContextMenuClick_(e: DomRepeatEvent<MerchantCart>) {
+    const index = e.model.index;
     ChromeCartProxy.getHandler().prepareForNavigation(
         this.cartItems[index].cartUrl, /*isNavigating=*/ false);
   }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
 }
 
 customElements.define(ChromeCartModuleElement.is, ChromeCartModuleElement);
 
-/** @return {!Promise<?HTMLElement>} */
-async function createCartElement() {
+async function createCartElement(): Promise<HTMLElement|null> {
   // getWarmWelcomeVisible makes server-side change and might flip the status of
   // whether welcome surface should show or not. Anything whose visibility
   // dependes on welcome surface (e.g. RBD consent) should check before
@@ -483,7 +439,6 @@
   return element;
 }
 
-/** @type {!ModuleDescriptor} */
-export const chromeCartDescriptor = new ModuleDescriptor(
+export const chromeCartDescriptor: ModuleDescriptor = new ModuleDescriptor(
     /*id=*/ 'chrome_cart',
     /*name=*/ loadTimeData.getString('modulesCartSentence'), createCartElement);
diff --git a/chrome/browser/resources/new_tab_page/modules/cart_v2/module.ts b/chrome/browser/resources/new_tab_page/modules/cart_v2/module.ts
index 75aa2cc..94f433d6 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart_v2/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/cart_v2/module.ts
@@ -12,11 +12,10 @@
 
 import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
 import {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
-import {DomRepeat, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DomRepeat, DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MerchantCart} from '../../chrome_cart.mojom-webui.js';
 import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
-import {RepeaterEvent} from '../../utils_ts.js';
 import {ChromeCartProxy} from '../cart/chrome_cart_proxy.js';
 import {ModuleDescriptorV2, ModuleHeight} from '../module_descriptor.js';
 
@@ -123,17 +122,16 @@
     return length === 1;
   }
 
-  private onCartMenuButtonClick_(e: RepeaterEvent<MerchantCart>) {
+  private onCartMenuButtonClick_(e: DomRepeatEvent<MerchantCart>) {
     e.preventDefault();
     e.stopPropagation();
-    const target = e.target as HTMLElement;
     this.currentMenuIndex_ = e.model.index;
     const merchant = this.cartItems[this.currentMenuIndex_].merchant;
     this.cartMenuHideItem_ =
         loadTimeData.getStringF('modulesCartCartMenuHideMerchant', merchant);
     this.cartMenuRemoveItem_ =
         loadTimeData.getStringF('modulesCartCartMenuRemoveMerchant', merchant);
-    this.$.cartActionMenu.showAt(target);
+    this.$.cartActionMenu.showAt(e.target as HTMLElement);
   }
 
   private async onCartHide_() {
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
index bf3f19d..5f76427 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/drive/BUILD.gn
@@ -2,27 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
-js_library("module") {
-  deps = [
-    ":drive_module_proxy",
-    "..:info_dialog",
-    "..:module_descriptor",
-    "../..:i18n_setup",
-    "//chrome/browser/new_tab_page/modules/drive:mojo_bindings_webui_js",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_auto_img",
-    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
-  ]
-}
-
-js_library("drive_module_proxy") {
-  deps =
-      [ "//chrome/browser/new_tab_page/modules/drive:mojo_bindings_webui_js" ]
-}
-
 html_to_js("web_components") {
-  js_files = [ "module.js" ]
+  js_files = [ "module.ts" ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.js b/chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.ts
similarity index 70%
rename from chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.js
rename to chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.ts
index 59013c52..d6a9b36 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.js
+++ b/chrome/browser/resources/new_tab_page/modules/drive/drive_module_proxy.ts
@@ -10,20 +10,16 @@
  * and receiving the browser response.
  */
 
-/** @type {?DriveHandlerRemote} */
-let handler = null;
+let handler: DriveHandlerRemote|null = null;
 
 export class DriveProxy {
-  /** @return {!DriveHandlerRemote} */
-  static getHandler() {
+  static getHandler(): DriveHandlerRemote {
     return handler || (handler = DriveHandler.getRemote());
   }
 
-  /** @param {!DriveHandlerRemote} newHandler */
-  static setHandler(newHandler) {
+  static setHandler(newHandler: DriveHandlerRemote) {
     handler = newHandler;
   }
 
-  /** @private */
-  constructor() {}
+  private constructor() {}
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/module.js b/chrome/browser/resources/new_tab_page/modules/drive/module.ts
similarity index 71%
rename from chrome/browser/resources/new_tab_page/modules/drive/module.js
rename to chrome/browser/resources/new_tab_page/modules/drive/module.ts
index 828b5f09..17af558 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/drive/module.ts
@@ -6,46 +6,45 @@
 import 'chrome://resources/cr_elements/cr_auto_img/cr_auto_img.js';
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {File} from '../../drive.mojom-webui.js';
-import {I18nBehavior, loadTimeData} from '../../i18n_setup.js';
+import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
 import {InfoDialogElement} from '../info_dialog.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
 import {DriveProxy} from './drive_module_proxy.js';
 
+interface DriveModuleElement {
+  $: {
+    infoDialogRender: CrLazyRenderElement<InfoDialogElement>,
+  };
+}
+
 /**
  * The Drive module, which serves as an inside look in to recent activity within
  * a user's Google Drive.
- * @polymer
- * @extends {PolymerElement}
  */
-class DriveModuleElement extends mixinBehaviors
-([I18nBehavior], PolymerElement) {
+class DriveModuleElement extends I18nMixin
+(PolymerElement) {
   static get is() {
     return 'ntp-drive-module';
   }
 
-  static get template() {
-    return html`{__html_template__}`;
-  }
-
   static get properties() {
     return {
-      /** @type {!Array<!File>} */
       files: Array,
     };
   }
 
-  /** @private */
-  onInfoButtonClick_() {
-    /** @type {InfoDialogElement} */ (this.$.infoDialogRender.get())
-        .showModal();
+  files: File[];
+
+  private onInfoButtonClick_() {
+    this.$.infoDialogRender.get().showModal();
   }
 
-  /** @private */
-  onDismissButtonClick_() {
+  private onDismissButtonClick_() {
     DriveProxy.getHandler().dismissModule();
     this.dispatchEvent(new CustomEvent('dismiss-module', {
       bubbles: true,
@@ -59,8 +58,7 @@
     }));
   }
 
-  /** @private */
-  onDisableButtonClick_() {
+  private onDisableButtonClick_() {
     this.dispatchEvent(new CustomEvent('disable-module', {
       bubbles: true,
       composed: true,
@@ -72,33 +70,25 @@
     }));
   }
 
-  /**
-   * @param {File} file
-   * @return {string}
-   * @private
-   */
-  getImageSrc_(file) {
+  private getImageSrc_(file: File): string {
     return 'https://drive-thirdparty.googleusercontent.com/32/type/' +
         file.mimeType;
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onFileClick_(e) {
+  private onFileClick_(e: DomRepeatEvent<File>) {
     this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
-    const index = this.$.fileRepeat.indexForElement(e.target);
+    const index = e.model.index;
     chrome.metricsPrivate.recordSmallCount('NewTabPage.Drive.FileClick', index);
   }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
 }
 
 customElements.define(DriveModuleElement.is, DriveModuleElement);
 
-/**
- * @return {!Promise<DriveModuleElement>}
- */
-async function createDriveElement() {
+async function createDriveElement(): Promise<DriveModuleElement|null> {
   const {files} = await DriveProxy.getHandler().getFiles();
   if (files.length === 0) {
     return null;
@@ -108,8 +98,7 @@
   return element;
 }
 
-/** @type {!ModuleDescriptor} */
-export const driveDescriptor = new ModuleDescriptor(
+export const driveDescriptor: ModuleDescriptor = new ModuleDescriptor(
     /*id=*/ 'drive',
     /*name=*/ loadTimeData.getString('modulesDriveSentence'),
     createDriveElement);
diff --git a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.ts b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.ts
index 9584edf..33ebd91a 100644
--- a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.ts
@@ -6,11 +6,10 @@
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 
 import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {File} from '../../drive.mojom-webui.js';
 import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
-import {RepeaterEvent} from '../../utils_ts.js';
 import {DriveProxy} from '../drive/drive_module_proxy.js';
 import {InfoDialogElement} from '../info_dialog.js';
 import {ModuleDescriptorV2, ModuleHeight} from '../module_descriptor.js';
@@ -56,7 +55,7 @@
     this.dispatchEvent(disableEvent);
   }
 
-  private onFileClick_(e: RepeaterEvent<File>) {
+  private onFileClick_(e: DomRepeatEvent<File>) {
     const clickFileEvent = new Event('usage', {composed: true});
     this.dispatchEvent(clickFileEvent);
     chrome.metricsPrivate.recordSmallCount(
diff --git a/chrome/browser/resources/new_tab_page/modules/photos/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/photos/BUILD.gn
index 52135d719..c9e2d66 100644
--- a/chrome/browser/resources/new_tab_page/modules/photos/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/photos/BUILD.gn
@@ -2,29 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
-js_library("module") {
-  deps = [
-    ":photos_module_proxy",
-    "..:module_descriptor",
-    "../..:i18n_setup",
-    "//chrome/browser/new_tab_page/modules/photos:mojo_bindings_webui_js",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_auto_img",
-    "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
-    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
-  ]
-}
-
-js_library("photos_module_proxy") {
-  deps = [
-    "//chrome/browser/new_tab_page/modules/photos:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:cr.m",
-  ]
-}
-
 html_to_js("web_components") {
-  js_files = [ "module.js" ]
+  js_files = [ "module.ts" ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/photos/module.js b/chrome/browser/resources/new_tab_page/modules/photos/module.ts
similarity index 69%
rename from chrome/browser/resources/new_tab_page/modules/photos/module.js
rename to chrome/browser/resources/new_tab_page/modules/photos/module.ts
index 5719fb8..092e67c 100644
--- a/chrome/browser/resources/new_tab_page/modules/photos/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/photos/module.ts
@@ -6,9 +6,10 @@
 import 'chrome://resources/cr_elements/cr_auto_img/cr_auto_img.js';
 import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
 
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {I18nBehavior, loadTimeData} from '../../i18n_setup.js';
+import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
 import {recordOccurence} from '../../metrics_utils.js';
 import {Memory} from '../../photos.mojom-webui.js';
 import {InfoDialogElement} from '../info_dialog.js';
@@ -20,100 +21,79 @@
  * List of possible OptIn status. This enum must match with the numbering for
  * NtpPhotosModuleOptInStatus in histogram/enums.xml. These values are persisted
  * to logs. Entries should not be renumbered, removed or reused.
- * @enum {number}
  */
-const OptInStatus = {
-  kHardOptOut: 0,
-  kOptIn: 1,
-  kSoftOptOut: 2,
-};
+enum OptInStatus {
+  kHardOptOut = 0,
+  kOptIn = 1,
+  kSoftOptOut = 2,
+}
 
-/** @param {!OptInStatus} optInStatus */
-function recordOptInStatus(optInStatus) {
+function recordOptInStatus(optInStatus: OptInStatus) {
   chrome.metricsPrivate.recordEnumerationValue(
       'NewTabPage.Photos.UserOptIn', optInStatus,
       Object.keys(OptInStatus).length);
 }
 
-/**
- * The Photos module, which serves Memories for the current user.
- * @polymer
- * @extends {PolymerElement}
- */
-class PhotosModuleElement extends mixinBehaviors
-([I18nBehavior], PolymerElement) {
+interface PhotosModuleElement {
+  $: {
+    infoDialogRender: CrLazyRenderElement<InfoDialogElement>,
+  };
+}
+
+/** The Photos module, which serves Memories for the current user.  */
+class PhotosModuleElement extends I18nMixin
+(PolymerElement) {
   static get is() {
     return 'ntp-photos-module';
   }
 
-  static get template() {
-    return html`{__html_template__}`;
-  }
-
   static get properties() {
     return {
-      /** @type {Array<!Memory>} */
       memories: Array,
 
-      /** @type {boolean} */
       showOptInScreen: {
         type: Boolean,
         reflectToAttribute: true,
       },
 
-      /** @type {boolean} */
       showSoftOptOutButton: Boolean,
 
-      /**
-       * @type {boolean}
-       * @private
-       */
       showExploreMore_:
           {type: Boolean, computed: 'computeShowExploreMore_(memories)'},
 
-      /**
-       * @type {string}
-       * @private
-       */
       headerChipText_:
-          {type: Boolean, computed: 'computeHeaderChipText_(showOptInScreen)'},
+          {type: String, computed: 'computeHeaderChipText_(showOptInScreen)'},
     };
   }
 
-  /** @override */
+  memories: Memory[];
+  showOptInScreen: boolean;
+  showSoftOptOutButton: boolean;
+  private showExploreMore_: boolean;
+  private headerChipText_: string;
+
   ready() {
     super.ready();
-    this.addEventListener('detect-impression', e => {
+    this.addEventListener('detect-impression', () => {
       chrome.metricsPrivate.recordBoolean(
           'NewTabPage.Photos.ModuleShown', this.showOptInScreen);
     });
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  computeShowExploreMore_() {
+  private computeShowExploreMore_(): boolean {
     return this.memories.length === 1;
   }
 
-  /**
-   * @return {string}
-   * @private
-   */
-  computeHeaderChipText_() {
+  private computeHeaderChipText_(): string {
     return this.showOptInScreen ? loadTimeData.getString('modulesPhotosNew') :
                                   '';
   }
 
-  /** @private */
-  onInfoButtonClick_() {
-    /** @type {InfoDialogElement} */ (this.$.infoDialogRender.get())
-        .showModal();
+  private onInfoButtonClick_() {
+    this.$.infoDialogRender.get().showModal();
   }
 
-  /** @private */
-  onDismissButtonClick_() {
+  private onDismissButtonClick_() {
     PhotosProxy.getHandler().dismissModule();
     this.dispatchEvent(new CustomEvent('dismiss-module', {
       bubbles: true,
@@ -125,8 +105,7 @@
     }));
   }
 
-  /** @private */
-  onSoftOptOutClick_() {
+  private onSoftOptOutClick_() {
     recordOptInStatus(OptInStatus.kSoftOptOut);
     PhotosProxy.getHandler().softOptOut();
     this.dispatchEvent(new CustomEvent('dismiss-module', {
@@ -139,8 +118,7 @@
     }));
   }
 
-  /** @private */
-  onDisableButtonClick_() {
+  private onDisableButtonClick_() {
     this.dispatchEvent(new CustomEvent('disable-module', {
       bubbles: true,
       composed: true,
@@ -152,44 +130,33 @@
     }));
   }
 
-  /** @private */
-  onImageLoadError_() {
+  private onImageLoadError_() {
     chrome.metricsPrivate.recordBoolean('NewTabPage.Photos.ImageLoad', false);
   }
 
-  /** @private */
-  onImageLoadSuccess_() {
+  private onImageLoadSuccess_() {
     chrome.metricsPrivate.recordBoolean('NewTabPage.Photos.ImageLoad', true);
   }
 
-  /** @private */
-  onOptInClick_() {
+  private onOptInClick_() {
     recordOptInStatus(OptInStatus.kOptIn);
     PhotosProxy.getHandler().onUserOptIn(true);
     this.showOptInScreen = false;
   }
 
-  /** @private */
-  onOptOutClick_() {
+  private onOptOutClick_() {
     recordOptInStatus(OptInStatus.kHardOptOut);
     PhotosProxy.getHandler().onUserOptIn(false);
     // Disable the module when user opt out.
     this.onDisableButtonClick_();
   }
 
-  /** @private */
-  onMemoryClick_() {
+  private onMemoryClick_() {
     this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
     PhotosProxy.getHandler().onMemoryOpen();
   }
 
-  /**
-   * @param {string} url
-   * @param {number} numMemories
-   * @return {string}
-   * @private
-   */
-  resizeImageUrl_(url, numMemories) {
+  private resizeImageUrl_(url: string, numMemories: number): string {
     // We request image dimensions related to the layout.
     let imgSize = '=w168-h164-p-k-rw-no';
     if (numMemories < 3) {
@@ -197,14 +164,15 @@
     }
     return url.replace('?', imgSize + '?');
   }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
 }
 
 customElements.define(PhotosModuleElement.is, PhotosModuleElement);
 
-/**
- * @return {!Promise<?PhotosModuleElement>}
- */
-async function createPhotosElement() {
+async function createPhotosElement(): Promise<PhotosModuleElement|null> {
   const {memories} = await PhotosProxy.getHandler().getMemories();
   const {showOptInScreen} =
       await PhotosProxy.getHandler().shouldShowOptInScreen();
@@ -221,8 +189,7 @@
   return element;
 }
 
-/** @type {!ModuleDescriptor} */
-export const photosDescriptor = new ModuleDescriptor(
+export const photosDescriptor: ModuleDescriptor = new ModuleDescriptor(
     /*id=*/ 'photos',
     /*name=*/ loadTimeData.getString('modulesPhotosSentence'),
     createPhotosElement);
diff --git a/chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.js b/chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.ts
similarity index 70%
rename from chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.js
rename to chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.ts
index 3105369..5e6cb6c 100644
--- a/chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.js
+++ b/chrome/browser/resources/new_tab_page/modules/photos/photos_module_proxy.ts
@@ -10,20 +10,16 @@
  * and receiving the browser response.
  */
 
-/** @type {?PhotosHandlerRemote} */
-let handler = null;
+let handler: PhotosHandlerRemote|null = null;
 
 export class PhotosProxy {
-  /** @return {!PhotosHandlerRemote} */
-  static getHandler() {
+  static getHandler(): PhotosHandlerRemote {
     return handler || (handler = PhotosHandler.getRemote());
   }
 
-  /** @param {!PhotosHandlerRemote} newHandler */
-  static setHandler(newHandler) {
+  static setHandler(newHandler: PhotosHandlerRemote) {
     handler = newHandler;
   }
 
-  /** @private */
-  constructor() {}
+  private constructor() {}
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
index 12d79db..5f76427 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/BUILD.gn
@@ -2,29 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
-js_library("module") {
-  deps = [
-    ":task_module_handler_proxy",
-    "..:info_dialog",
-    "..:module_descriptor",
-    "../..:i18n_setup",
-    "//chrome/browser/new_tab_page/modules/task_module:mojo_bindings_webui_js",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_auto_img",
-    "//ui/webui/resources/cr_elements/cr_grid",
-    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
-  ]
-}
-
-js_library("task_module_handler_proxy") {
-  deps = [
-    "//chrome/browser/new_tab_page/modules/task_module:mojo_bindings_webui_js",
-  ]
-}
-
 html_to_js("web_components") {
-  js_files = [ "module.js" ]
+  js_files = [ "module.ts" ]
 }
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/module.js b/chrome/browser/resources/new_tab_page/modules/task_module/module.ts
similarity index 71%
rename from chrome/browser/resources/new_tab_page/modules/task_module/module.js
rename to chrome/browser/resources/new_tab_page/modules/task_module/module.ts
index 1897973..1eb961d 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/module.js
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/module.ts
@@ -7,56 +7,52 @@
 import 'chrome://resources/cr_elements/cr_auto_img/cr_auto_img.js';
 import 'chrome://resources/cr_elements/hidden_style_css.m.js';
 
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {I18nBehavior, loadTimeData} from '../../i18n_setup.js';
-import {Task, TaskModuleType} from '../../task_module.mojom-webui.js';
+import {I18nMixin, loadTimeData} from '../../i18n_setup.js';
+import {RelatedSearch, Task, TaskItem, TaskModuleType} from '../../task_module.mojom-webui.js';
 import {InfoDialogElement} from '../info_dialog.js';
 import {ModuleDescriptor} from '../module_descriptor.js';
 
 import {TaskModuleHandlerProxy} from './task_module_handler_proxy.js';
 
+interface TaskModuleElement {
+  $: {
+    infoDialogRender: CrLazyRenderElement<InfoDialogElement>,
+  };
+}
+
 /**
  * Implements the UI of a task module. This module shows a currently active task
  * search journey and provides a way for the user to continue that search
  * journey.
- * @polymer
- * @extends {PolymerElement}
  */
-class TaskModuleElement extends mixinBehaviors
-([I18nBehavior], PolymerElement) {
+class TaskModuleElement extends I18nMixin
+(PolymerElement) {
   static get is() {
     return 'ntp-task-module';
   }
 
-  static get template() {
-    return html`{__html_template__}`;
-  }
-
   static get properties() {
     return {
-      /** @type {!TaskModuleType} */
       taskModuleType: {
         type: Number,
         observer: 'onTaskModuleTypeChange_',
       },
 
-      /** @type {!Task} */
       task: Object,
 
-      /** @private {string} */
       title_: {
         type: String,
         computed: 'computeTitle_(taskModuleType, task)',
       },
 
-      /** @private {string} */
       dismissName_: {
         type: String,
         computed: 'computeDismissName_(taskModuleType, task)',
       },
 
-      /** @private {string} */
       disableName_: {
         type: String,
         computed: 'computeDisableName_(taskModuleType)',
@@ -64,17 +60,15 @@
     };
   }
 
-  constructor() {
-    super();
-    /** @type {IntersectionObserver} */
-    this.intersectionObserver_ = null;
-  }
+  taskModuleType: TaskModuleType;
+  task: Task;
+  private title_: string;
+  private dismissName_: string;
+  private disableName_: string;
 
-  /**
-   * @return {string}
-   * @private
-   */
-  computeTitle_() {
+  private intersectionObserver_: IntersectionObserver|null = null;
+
+  private computeTitle_(): string {
     switch (this.taskModuleType) {
       case TaskModuleType.kRecipe:
         return loadTimeData.getString('modulesRecipeTasksSentence');
@@ -85,11 +79,7 @@
     }
   }
 
-  /**
-   * @return {string}
-   * @private
-   */
-  computeDismissName_() {
+  private computeDismissName_(): string {
     switch (this.taskModuleType) {
       case TaskModuleType.kRecipe:
         return loadTimeData.getString('modulesRecipeTasksLowerThese');
@@ -100,11 +90,7 @@
     }
   }
 
-  /**
-   * @return {string}
-   * @private
-   */
-  computeDisableName_() {
+  private computeDisableName_(): string {
     switch (this.taskModuleType) {
       case TaskModuleType.kRecipe:
         return loadTimeData.getString('modulesRecipeTasksLower');
@@ -115,24 +101,15 @@
     }
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  isRecipe_() {
+  private isRecipe_(): boolean {
     return this.taskModuleType === TaskModuleType.kRecipe;
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  isShopping_() {
+  private isShopping_(): boolean {
     return this.taskModuleType === TaskModuleType.kShopping;
   }
 
-  /** @private */
-  onTaskModuleTypeChange_() {
+  private onTaskModuleTypeChange_() {
     switch (this.taskModuleType) {
       case TaskModuleType.kRecipe:
         this.toggleAttribute('recipe');
@@ -143,36 +120,25 @@
     }
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onTaskItemClick_(e) {
-    const index = this.$.taskItemsRepeat.indexForElement(e.target);
+  private onTaskItemClick_(e: DomRepeatEvent<TaskItem>) {
+    const index = e.model.index;
     TaskModuleHandlerProxy.getHandler().onTaskItemClicked(
         this.taskModuleType, index);
     this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onPillClick_(e) {
-    const index = this.$.relatedSearchesRepeat.indexForElement(e.target);
+  private onPillClick_(e: DomRepeatEvent<RelatedSearch>) {
+    const index = e.model.index;
     TaskModuleHandlerProxy.getHandler().onRelatedSearchClicked(
         this.taskModuleType, index);
     this.dispatchEvent(new Event('usage', {bubbles: true, composed: true}));
   }
 
-  /** @private */
-  onInfoButtonClick_() {
-    /** @type {InfoDialogElement} */ (this.$.infoDialogRender.get())
-        .showModal();
+  private onInfoButtonClick_() {
+    this.$.infoDialogRender.get().showModal();
   }
 
-  /** @private */
-  onDismissButtonClick_() {
+  private onDismissButtonClick_() {
     TaskModuleHandlerProxy.getHandler().dismissTask(
         this.taskModuleType, this.task.name);
     let taskName = '';
@@ -194,8 +160,7 @@
     }));
   }
 
-  /** @private */
-  onDisableButtonClick_() {
+  private onDisableButtonClick_() {
     this.dispatchEvent(new CustomEvent('disable-module', {
       bubbles: true,
       composed: true,
@@ -206,18 +171,16 @@
     }));
   }
 
-  /** @private */
-  onRestore_() {
+  private onRestore_() {
     TaskModuleHandlerProxy.getHandler().restoreTask(
         this.taskModuleType, this.task.name);
   }
 
-  /** @private */
-  onDomChange_() {
+  private onDomChange_() {
     if (!this.intersectionObserver_) {
       this.intersectionObserver_ = new IntersectionObserver(entries => {
         entries.forEach(({intersectionRatio, target}) => {
-          target.style.visibility =
+          (target as HTMLElement).style.visibility =
               intersectionRatio < 1 ? 'hidden' : 'visible';
         });
         this.dispatchEvent(new Event('visibility-update'));
@@ -225,15 +188,19 @@
     } else {
       this.intersectionObserver_.disconnect();
     }
-    this.shadowRoot.querySelectorAll('.task-item, .pill')
-        .forEach(el => this.intersectionObserver_.observe(el));
+    this.shadowRoot!.querySelectorAll('.task-item, .pill')
+        .forEach(el => this.intersectionObserver_!.observe(el));
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
   }
 }
 
 customElements.define(TaskModuleElement.is, TaskModuleElement);
 
-/** @return {!Promise<?HTMLElement>} */
-async function createModule(taskModuleType) {
+async function createModule(taskModuleType: TaskModuleType):
+    Promise<HTMLElement|null> {
   const {task} =
       await TaskModuleHandlerProxy.getHandler().getPrimaryTask(taskModuleType);
   if (!task) {
@@ -245,14 +212,12 @@
   return element;
 }
 
-/** @type {!ModuleDescriptor} */
-export const recipeTasksDescriptor = new ModuleDescriptor(
+export const recipeTasksDescriptor: ModuleDescriptor = new ModuleDescriptor(
     /*id=*/ 'recipe_tasks',
     /*name=*/ loadTimeData.getString('modulesRecipeTasksSentence'),
     createModule.bind(null, TaskModuleType.kRecipe));
 
-/** @type {!ModuleDescriptor} */
-export const shoppingTasksDescriptor = new ModuleDescriptor(
+export const shoppingTasksDescriptor: ModuleDescriptor = new ModuleDescriptor(
     /*id=*/ 'shopping_tasks',
     /*name=*/ loadTimeData.getString('modulesShoppingTasksSentence'),
     createModule.bind(null, TaskModuleType.kShopping));
diff --git a/chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.js b/chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.ts
similarity index 68%
rename from chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.js
rename to chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.ts
index 587c51b..9985924 100644
--- a/chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.js
+++ b/chrome/browser/resources/new_tab_page/modules/task_module/task_module_handler_proxy.ts
@@ -9,20 +9,16 @@
  * interface used for retrieving a shopping task for a task module.
  */
 
-/** @type {?TaskModuleHandlerRemote} */
-let handler = null;
+let handler: TaskModuleHandlerRemote|null = null;
 
 export class TaskModuleHandlerProxy {
-  /** @return {!TaskModuleHandlerRemote} */
-  static getHandler() {
+  static getHandler(): TaskModuleHandlerRemote {
     return handler || (handler = TaskModuleHandler.getRemote());
   }
 
-  /** @param {!TaskModuleHandlerRemote} newHandler */
-  static setHandler(newHandler) {
+  static setHandler(newHandler: TaskModuleHandlerRemote) {
     handler = newHandler;
   }
 
-  /** @private */
-  constructor() {}
+  private constructor() {}
 }
diff --git a/chrome/browser/resources/new_tab_page/utils_ts.ts b/chrome/browser/resources/new_tab_page/utils_ts.ts
index 22d3c140..231db9a 100644
--- a/chrome/browser/resources/new_tab_page/utils_ts.ts
+++ b/chrome/browser/resources/new_tab_page/utils_ts.ts
@@ -2,15 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/** Event interface for dom-repeat event. */
-// TODO(dpapad): Move this to a shared location and reuse across WebUIs.
-export interface RepeaterEvent<M> extends Event {
-  model: {
-    item: M,
-    index: number,
-  };
-}
-
 /**
  * Queries |selector| on |element|'s shadow root and returns the resulting
  * element if there is any.
diff --git a/chrome/browser/resources/settings/metrics_browser_proxy.ts b/chrome/browser/resources/settings/metrics_browser_proxy.ts
index 850219c9..a392f6a 100644
--- a/chrome/browser/resources/settings/metrics_browser_proxy.ts
+++ b/chrome/browser/resources/settings/metrics_browser_proxy.ts
@@ -108,6 +108,38 @@
   COUNT = 10,
 }
 
+/**
+ * This enum covers all possible combinations of the start and end
+ * settings states for each Privacy guide fragment, allowing metrics to see if
+ * users change their settings inside of Privacy guide or not. The format is
+ * settingAtStart-To-settingAtEnd.
+ *
+ * These values are persisted to logs. Entries should not be renumbered and
+ * numeric values should never be reused.
+ *
+ * Must be kept in sync with SettingsPrivacyGuideSettingsStates in enums.xml.
+ */
+export enum PrivacyGuideSettingsStates {
+  MSBB_ON_TO_ON = 0,
+  MSBB_ON_TO_OFF = 1,
+  MSBB_OFF_TO_ON = 2,
+  MSBB_OFF_TO_OFF = 3,
+  BLOCK_3P_INCOGNITO_TO_3P_INCOGNITO = 4,
+  BLOCK_3P_INCOGNITO_TO_3P = 5,
+  BLOCK_3P_TO_3P_INCOGNITO = 6,
+  BLOCK_3P_TO_3P = 7,
+  HISTORY_SYNC_ON_TO_ON = 8,
+  HISTORY_SYNC_ON_TO_OFF = 9,
+  HISTORY_SYNC_OFF_TO_ON = 10,
+  HISTORY_SYNC_OFF_TO_OFF = 11,
+  SAFE_BROWSING_ENHANCED_TO_ENHANCED = 12,
+  SAFE_BROWSING_ENHANCED_TO_STANDARD = 13,
+  SAFE_BROWSING_STANDARD_TO_ENHANCED = 14,
+  SAFE_BROWSING_STANDARD_TO_STANDARD = 15,
+  // Leave this at the end.
+  COUNT = 16,
+}
+
 export interface MetricsBrowserProxy {
   /**
    * Helper function that calls recordAction with one action from
@@ -148,6 +180,13 @@
    */
   recordPrivacyGuideEntryExitHistogram(interaction: PrivacyGuideInteractions):
       void;
+
+  /**
+   * Helper function that calls recordHistogram for the
+   * Settings.PrivacyGuide.SettingsStates histogram
+   */
+  recordPrivacyGuideSettingsStatesHistogram(state: PrivacyGuideSettingsStates):
+      void;
 }
 
 export class MetricsBrowserProxyImpl implements MetricsBrowserProxy {
@@ -194,6 +233,13 @@
     ]);
   }
 
+  recordPrivacyGuideSettingsStatesHistogram(state: PrivacyGuideSettingsStates) {
+    chrome.send('metricsHandler:recordInHistogram', [
+      'Settings.PrivacyGuide.SettingsStates', state,
+      PrivacyGuideSettingsStates.COUNT
+    ]);
+  }
+
   static getInstance(): MetricsBrowserProxy {
     return instance || (instance = new MetricsBrowserProxyImpl());
   }
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.html b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.html
index 3654a65..2ab77a6 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.html
@@ -11,7 +11,8 @@
 <settings-radio-group id="cookiesRadioGroup"
     pref="{{prefs.generated.cookie_primary_setting}}"
     selectable-elements="settings-collapse-radio-button">
-  <settings-collapse-radio-button pref="[[prefs.generated.cookie_primary_setting]]"
+  <settings-collapse-radio-button id="block3PIncognito"
+      pref="[[prefs.generated.cookie_primary_setting]]"
       name="[[cookiePrimarySettingEnum_.BLOCK_THIRD_PARTY_INCOGNITO]]"
       label="$i18n{privacyReviewCookiesCardBlockTpcIncognitoSubheader}"
       expand-aria-label=
@@ -45,7 +46,8 @@
       </div>
     </div>
   </settings-collapse-radio-button>
-  <settings-collapse-radio-button pref="[[prefs.generated.cookie_primary_setting]]"
+  <settings-collapse-radio-button id="block3P"
+      pref="[[prefs.generated.cookie_primary_setting]]"
       name="[[cookiePrimarySettingEnum_.BLOCK_THIRD_PARTY]]"
       label="$i18n{privacyReviewCookiesCardBlockTpcSubheader}"
       expand-aria-label="$i18n{cookiePageBlockThirdExpandA11yLabel}">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts
index 60d0d8f1..51292e3 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts
@@ -14,9 +14,15 @@
 import '../../privacy_page/collapse_radio_button.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyGuideSettingsStates} from '../../metrics_browser_proxy.js';
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {CookiePrimarySetting} from '../../site_settings/site_settings_prefs_browser_proxy.js';
 
-export class PrivacyReviewCookiesFragmentElement extends PolymerElement {
+const PrivacyReviewCookiesFragmentBase = PrefsMixin(PolymerElement);
+
+export class PrivacyReviewCookiesFragmentElement extends
+    PrivacyReviewCookiesFragmentBase {
   static get is() {
     return 'privacy-review-cookies-fragment';
   }
@@ -44,6 +50,40 @@
       },
     };
   }
+
+  private metricsBrowserProxy_: MetricsBrowserProxy =
+      MetricsBrowserProxyImpl.getInstance();
+  private startStateBlock3PIncognito_: boolean;
+
+  ready() {
+    super.ready();
+    this.addEventListener('view-enter-start', this.onViewEnterStart_);
+    this.addEventListener('view-exit-finish', this.onViewExitFinish_);
+  }
+
+  private onViewEnterStart_() {
+    this.startStateBlock3PIncognito_ =
+        this.getPref('generated.cookie_primary_setting').value ===
+        CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO;
+  }
+
+  private onViewExitFinish_() {
+    const endStateBlock3PIncognito =
+        this.getPref('generated.cookie_primary_setting').value ===
+        CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO;
+
+    let state: PrivacyGuideSettingsStates|null = null;
+    if (this.startStateBlock3PIncognito_) {
+      state = endStateBlock3PIncognito ?
+          PrivacyGuideSettingsStates.BLOCK_3P_INCOGNITO_TO_3P_INCOGNITO :
+          PrivacyGuideSettingsStates.BLOCK_3P_INCOGNITO_TO_3P;
+    } else {
+      state = endStateBlock3PIncognito ?
+          PrivacyGuideSettingsStates.BLOCK_3P_TO_3P_INCOGNITO :
+          PrivacyGuideSettingsStates.BLOCK_3P_TO_3P;
+    }
+    this.metricsBrowserProxy_.recordPrivacyGuideSettingsStatesHistogram(state!);
+  }
 }
 
 customElements.define(
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts
index f618a90..2cf43d4 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts
@@ -18,6 +18,7 @@
 
 import {BaseMixin} from '../../base_mixin.js';
 import {SettingsToggleButtonElement} from '../../controls/settings_toggle_button.js';
+import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyGuideSettingsStates} from '../../metrics_browser_proxy.js';
 import {SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, syncPrefsIndividualDataTypes} from '../../people_page/sync_browser_proxy.js';
 import {routes} from '../../route.js';
 import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js';
@@ -79,6 +80,15 @@
    */
   private syncAllCache_: boolean|null = null;
   private historySyncVirtualPref_: chrome.settingsPrivate.PrefObject;
+  private metricsBrowserProxy_: MetricsBrowserProxy =
+      MetricsBrowserProxyImpl.getInstance();
+  private startStateHistorySyncOn_: boolean;
+  /*
+   * This is needed as the nature of SyncPrefs means there is a chance they are
+   * not actually initialized before view-enter-start, so the pref value is read
+   * when the page fires its on-load update/initialization of SyncPrefs.
+   */
+  private firstSyncPrefUpdate_: boolean = true;
 
   ready() {
     super.ready();
@@ -87,6 +97,24 @@
         'sync-prefs-changed',
         (syncPrefs: SyncPrefs) => this.onSyncPrefsChange_(syncPrefs));
     this.syncBrowserProxy_.sendSyncPrefsChanged();
+    this.addEventListener('view-exit-finish', this.onViewExitFinish_);
+  }
+
+  private onViewExitFinish_() {
+    const endStateHistorySyncOn = this.syncPrefs_.typedUrlsSynced;
+    let state: PrivacyGuideSettingsStates|null = null;
+    if (this.startStateHistorySyncOn_) {
+      state = endStateHistorySyncOn ?
+          PrivacyGuideSettingsStates.HISTORY_SYNC_ON_TO_ON :
+          PrivacyGuideSettingsStates.HISTORY_SYNC_ON_TO_OFF;
+    } else {
+      state = endStateHistorySyncOn ?
+          PrivacyGuideSettingsStates.HISTORY_SYNC_OFF_TO_ON :
+          PrivacyGuideSettingsStates.HISTORY_SYNC_OFF_TO_OFF;
+    }
+    this.metricsBrowserProxy_.recordPrivacyGuideSettingsStatesHistogram(state!);
+
+    this.firstSyncPrefUpdate_ = true;
   }
 
   currentRouteChanged(newRoute: Route) {
@@ -107,6 +135,11 @@
     this.set(
         'historySyncVirtualPref_.value',
         this.syncPrefs_.syncAllDataTypes || this.syncPrefs_.typedUrlsSynced);
+
+    if (this.firstSyncPrefUpdate_) {
+      this.startStateHistorySyncOn_ = this.syncPrefs_.typedUrlsSynced;
+      this.firstSyncPrefUpdate_ = false;
+    }
   }
 
   private onToggleClick_() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts
index b80fb0a..c4fc1e9 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts
@@ -14,7 +14,13 @@
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-export class PrivacyReviewMsbbFragmentElement extends PolymerElement {
+import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyGuideSettingsStates} from '../../metrics_browser_proxy.js';
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
+
+const PrivacyReviewMsbbFragmentBase = PrefsMixin(PolymerElement);
+
+export class PrivacyReviewMsbbFragmentElement extends
+    PrivacyReviewMsbbFragmentBase {
   static get is() {
     return 'privacy-review-msbb-fragment';
   }
@@ -34,6 +40,36 @@
       },
     };
   }
+
+  private metricsBrowserProxy_: MetricsBrowserProxy =
+      MetricsBrowserProxyImpl.getInstance();
+  private startStateMsbbOn_: boolean;
+
+  ready() {
+    super.ready();
+    this.addEventListener('view-enter-start', this.onViewEnterStart_);
+    this.addEventListener('view-exit-finish', this.onViewExitFinish_);
+  }
+
+  private onViewEnterStart_() {
+    this.startStateMsbbOn_ =
+        this.getPref('url_keyed_anonymized_data_collection.enabled').value;
+  }
+
+  private onViewExitFinish_() {
+    const endStateMsbbOn =
+        this.getPref('url_keyed_anonymized_data_collection.enabled').value;
+
+    let state: PrivacyGuideSettingsStates|null = null;
+    if (this.startStateMsbbOn_) {
+      state = endStateMsbbOn ? PrivacyGuideSettingsStates.MSBB_ON_TO_ON :
+                               PrivacyGuideSettingsStates.MSBB_ON_TO_OFF;
+    } else {
+      state = endStateMsbbOn ? PrivacyGuideSettingsStates.MSBB_OFF_TO_ON :
+                               PrivacyGuideSettingsStates.MSBB_OFF_TO_OFF;
+    }
+    this.metricsBrowserProxy_.recordPrivacyGuideSettingsStatesHistogram(state!);
+  }
 }
 
 customElements.define(
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.html b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.html
index be30895e..a78da34b 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.html
@@ -11,7 +11,8 @@
 <settings-radio-group id="safeBrowsingRadioGroup"
     pref="{{prefs.generated.safe_browsing}}"
     selectable-elements="settings-collapse-radio-button">
-  <settings-collapse-radio-button pref="[[prefs.generated.safe_browsing]]"
+  <settings-collapse-radio-button id="safeBrowsingRadioEnhanced"
+      pref="[[prefs.generated.safe_browsing]]"
       name="[[safeBrowsingSettingEnum_.ENHANCED]]"
       label="$i18n{safeBrowsingEnhanced}"
       sub-label="$i18n{safeBrowsingEnhancedDesc}"
@@ -57,7 +58,8 @@
         </div>
       </div>
   </settings-collapse-radio-button>
-  <settings-collapse-radio-button pref="[[prefs.generated.safe_browsing]]"
+  <settings-collapse-radio-button id="safeBrowsingRadioStandard"
+      pref="[[prefs.generated.safe_browsing]]"
       name="[[safeBrowsingSettingEnum_.STANDARD]]"
       label="$i18n{safeBrowsingStandard}"
       sub-label="$i18n{safeBrowsingStandardDesc}"
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts
index 32c02a2..a9cc5049 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts
@@ -14,9 +14,15 @@
 import '../../privacy_page/collapse_radio_button.js';
 
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyGuideSettingsStates} from '../../metrics_browser_proxy.js';
+import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {SafeBrowsingSetting} from '../../privacy_page/security_page.js';
 
-export class PrivacyReviewSafeBrowsingFragmentElement extends PolymerElement {
+const PrivacyReviewSafeBrowsingFragmentBase = PrefsMixin(PolymerElement);
+
+export class PrivacyReviewSafeBrowsingFragmentElement extends
+    PrivacyReviewSafeBrowsingFragmentBase {
   static get is() {
     return 'privacy-review-safe-browsing-fragment';
   }
@@ -44,6 +50,38 @@
       },
     };
   }
+
+  private metricsBrowserProxy_: MetricsBrowserProxy =
+      MetricsBrowserProxyImpl.getInstance();
+  private startStateEnhanced_: boolean;
+
+  ready() {
+    super.ready();
+    this.addEventListener('view-enter-start', this.onViewEnterStart_);
+    this.addEventListener('view-exit-finish', this.onViewExitFinish_);
+  }
+
+  private onViewEnterStart_() {
+    this.startStateEnhanced_ = this.getPref('generated.safe_browsing').value ===
+        SafeBrowsingSetting.ENHANCED;
+  }
+
+  private onViewExitFinish_() {
+    const endStateEnhanced = this.getPref('generated.safe_browsing').value ===
+        SafeBrowsingSetting.ENHANCED;
+
+    let state: PrivacyGuideSettingsStates|null = null;
+    if (this.startStateEnhanced_) {
+      state = endStateEnhanced ?
+          PrivacyGuideSettingsStates.SAFE_BROWSING_ENHANCED_TO_ENHANCED :
+          PrivacyGuideSettingsStates.SAFE_BROWSING_ENHANCED_TO_STANDARD;
+    } else {
+      state = endStateEnhanced ?
+          PrivacyGuideSettingsStates.SAFE_BROWSING_STANDARD_TO_ENHANCED :
+          PrivacyGuideSettingsStates.SAFE_BROWSING_STANDARD_TO_STANDARD;
+    }
+    this.metricsBrowserProxy_.recordPrivacyGuideSettingsStatesHistogram(state!);
+  }
 }
 
 customElements.define(
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts
index 59fc870..64274030 100644
--- a/chrome/browser/resources/settings/settings.ts
+++ b/chrome/browser/resources/settings/settings.ts
@@ -42,7 +42,7 @@
 export {HatsBrowserProxy, HatsBrowserProxyImpl, TrustSafetyInteraction} from './hats_browser_proxy.js';
 export {loadTimeData} from './i18n_setup.js';
 export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from './lifetime_browser_proxy.js';
-export {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, PrivacyGuideInteractions, SafeBrowsingInteractions, SafetyCheckInteractions} from './metrics_browser_proxy.js';
+export {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions} from './metrics_browser_proxy.js';
 export {NtpExtension, OnStartupBrowserProxy, OnStartupBrowserProxyImpl} from './on_startup_page/on_startup_browser_proxy.js';
 export {SettingsOnStartupPageElement} from './on_startup_page/on_startup_page.js';
 export {SettingsStartupUrlDialogElement} from './on_startup_page/startup_url_dialog.js';
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
index 7753f2d2..ce44c6b 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
@@ -23,19 +23,13 @@
     width: 100%;
   }
 
-<if expr="not lacros">
-  /* The settings button is right next to the action button on Lacros. */
-  .action-container #settingsButton {
-    left: var(--action-container-padding);
+  /* The settings button is at the start of the line (opposite to other buttons)
+     when sync is optional. */
+  .sync-optional #settingsButton {
+    inset-inline-start: var(--action-container-padding);
     position: absolute;
   }
 
-  :host-context([dir='rtl']) .action-container #settingsButton {
-    left: auto;
-    right: var(--action-container-padding);
-  }
-</if>
-
   /* Old design */
   #illustration-container {
     height: 168px;
@@ -266,7 +260,7 @@
     <div id="old-footer" class="message-container secondary">
       $i18n{syncConfirmationSettingsInfo}
     </div>
-    <div class="action-container">
+    <div class$="action-container [[isSyncForcedClass_]]">
       <cr-button class="action-button" id="confirmButton"
           on-click="onConfirm_" consent-confirmation autofocus>
         $i18n{syncConfirmationConfirmLabel}
@@ -277,11 +271,9 @@
           $i18n{syncConfirmationSettingsLabel}
         </cr-button>
       </if>
-      <if expr="not lacros">
-        <cr-button id="cancelButton" on-click="onUndo_">
-          $i18n{syncConfirmationUndoLabel}
-        </cr-button>
-      </if>
+      <cr-button id="cancelButton" on-click="onUndo_" hidden="[[syncForced_]]">
+        $i18n{syncConfirmationUndoLabel}
+      </cr-button>
       <if expr="not is_macosx and not is_linux">
         <cr-button id="settingsButton" on-click="onGoToSettings_"
             consent-confirmation>
@@ -316,7 +308,7 @@
         <span consent-description>$i18n{syncConfirmationSyncInfoDesc}</span>.
       </div>
     </div>
-    <div id="buttonsContainer" class="action-container">
+    <div id="buttonsContainer" class$="action-container [[syncOptionalClass_]]">
       <cr-button class="action-button" id="confirmButton"
           on-click="onConfirm_" consent-confirmation>
         $i18n{syncConfirmationConfirmLabel}
@@ -327,11 +319,9 @@
           $i18n{syncConfirmationSettingsLabel}
         </cr-button>
       </if>
-      <if expr="not lacros">
-        <cr-button id="notNowButton" on-click="onUndo_">
-          $i18n{syncConfirmationUndoLabel}
-        </cr-button>
-      </if>
+      <cr-button id="notNowButton" on-click="onUndo_" hidden="[[syncForced_]]">
+        $i18n{syncConfirmationUndoLabel}
+      </cr-button>
       <if expr="not is_macosx and not is_linux">
         <cr-button id="settingsButton" on-click="onGoToSettings_"
             consent-confirmation>
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
index 5aa8669..2a449748 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
@@ -73,7 +73,24 @@
       showEnterpriseBadge_: {
         type: Boolean,
         value: false,
-      }
+      },
+
+      syncForced_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('syncForced');
+        }
+      },
+
+      syncOptionalClass_: {
+        type: String,
+        value() {
+          if (loadTimeData.getBoolean('syncForced')) {
+            return '';
+          }
+          return 'sync-optional';
+        },
+      },
     };
   }
 
@@ -82,6 +99,8 @@
   private isNewDesign_: boolean;
   private highlightColor_: string;
   private showEnterpriseBadge_: boolean;
+  private syncForced_: boolean;
+  private syncOptionalClass_: string;
   private syncConfirmationBrowserProxy_: SyncConfirmationBrowserProxy =
       SyncConfirmationBrowserProxyImpl.getInstance();
 
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
index 9552603..2b687ca 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller.cc
@@ -183,8 +183,13 @@
       credential.is_affiliation_based_match().value());
   driver_->TouchToFillClosed(ShowVirtualKeyboard(false));
 
-  std::exchange(driver_, nullptr)
-      ->FillSuggestion(credential.username(), credential.password());
+  driver_->FillSuggestion(credential.username(), credential.password());
+
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kTouchToFillPasswordSubmission)) {
+    driver_->TriggerFormSubmission();
+  }
+  driver_ = nullptr;
 
   base::UmaHistogramEnumeration("PasswordManager.TouchToFill.Outcome",
                                 TouchToFillOutcome::kCredentialFilled);
diff --git a/chrome/browser/touch_to_fill/touch_to_fill_controller_unittest.cc b/chrome/browser/touch_to_fill/touch_to_fill_controller_unittest.cc
index 373dd21..0490677b 100644
--- a/chrome/browser/touch_to_fill/touch_to_fill_controller_unittest.cc
+++ b/chrome/browser/touch_to_fill/touch_to_fill_controller_unittest.cc
@@ -54,6 +54,7 @@
   MOCK_METHOD2(FillSuggestion,
                void(const std::u16string&, const std::u16string&));
   MOCK_METHOD1(TouchToFillClosed, void(ShowVirtualKeyboard));
+  MOCK_METHOD0(TriggerFormSubmission, void());
   MOCK_CONST_METHOD0(GetLastCommittedURL, const GURL&());
 };
 
@@ -98,6 +99,9 @@
     ON_CALL(driver_, GetLastCommittedURL())
         .WillByDefault(ReturnRefOfCopy(GURL(kExampleCom)));
 
+    // By default, don't trigger a form submission.
+    EXPECT_CALL(driver_, TriggerFormSubmission()).Times(0);
+
     scoped_feature_list_.InitAndEnableFeature(
         password_manager::features::kBiometricTouchToFill);
   }
@@ -126,6 +130,10 @@
     return touch_to_fill_controller_;
   }
 
+  base::test::ScopedFeatureList& scoped_feature_list() {
+    return scoped_feature_list_;
+  }
+
  private:
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@@ -176,6 +184,33 @@
           TouchToFillController::UserAction::kSelectedCredential));
 }
 
+TEST_F(TouchToFillControllerTest, Show_Fill_And_Submit) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      password_manager::features::kTouchToFillPasswordSubmission);
+
+  std::unique_ptr<TouchToFillController> controller_no_auth =
+      CreateNoAuthController();
+  std::unique_ptr<MockTouchToFillView> mock_view =
+      std::make_unique<MockTouchToFillView>();
+  MockTouchToFillView* weak_view = mock_view.get();
+  controller_no_auth->set_view(std::move(mock_view));
+
+  UiCredential credentials[] = {
+      MakeUiCredential({.username = "alice", .password = "p4ssw0rd"})};
+
+  EXPECT_CALL(*weak_view, Show(Eq(GURL(kExampleCom)), IsOriginSecure(true),
+                               ElementsAreArray(credentials)));
+  controller_no_auth->Show(credentials, driver().AsWeakPtr());
+
+  EXPECT_CALL(driver(), FillSuggestion(std::u16string(u"alice"),
+                                       std::u16string(u"p4ssw0rd")));
+  EXPECT_CALL(driver(), TouchToFillClosed(ShowVirtualKeyboard(false)));
+  EXPECT_CALL(driver(), TriggerFormSubmission());
+
+  controller_no_auth->OnCredentialSelected(credentials[0]);
+}
+
 TEST_F(TouchToFillControllerTest, Show_And_Fill_No_Auth_Available) {
   UiCredential credentials[] = {
       MakeUiCredential({.username = "alice", .password = "p4ssw0rd"})};
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 1c629898..51337f4 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1993,6 +1993,8 @@
       "app_list/search/ranking/best_match_ranker.cc",
       "app_list/search/ranking/best_match_ranker.h",
       "app_list/search/ranking/constants.h",
+      "app_list/search/ranking/continue_ranker.cc",
+      "app_list/search/ranking/continue_ranker.h",
       "app_list/search/ranking/filtering_ranker.cc",
       "app_list/search/ranking/filtering_ranker.h",
       "app_list/search/ranking/ftrl_ranker.cc",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn
index 3684c1b..cc52e39 100644
--- a/chrome/browser/ui/android/omnibox/BUILD.gn
+++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -87,6 +87,7 @@
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutView.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java",
@@ -110,6 +111,11 @@
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/ExploreIconProvider.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java",
@@ -358,6 +364,7 @@
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutViewTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
index a190f84..c4602fd2 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -41,6 +41,8 @@
 import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderViewBinder;
 import org.chromium.chrome.browser.omnibox.suggestions.mostvisited.ExploreIconProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.mostvisited.MostVisitedTilesProcessor;
+import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionView;
+import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionViewBinder;
 import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionView;
 import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionViewBinder;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
@@ -200,6 +202,12 @@
                         OmniboxSuggestionUiType.HEADER,
                         parent -> new HeaderView(parent.getContext()),
                         HeaderViewBinder::bind);
+
+                adapter.registerType(
+                        OmniboxSuggestionUiType.PEDAL_SUGGESTION,
+                        parent -> new PedalSuggestionView<View>(
+                                parent.getContext(), R.layout.omnibox_basic_suggestion),
+                        new PedalSuggestionViewBinder<View>(SuggestionViewViewBinder::bind));
                 // clang-format on
 
                 ViewGroup container = (ViewGroup) ((ViewStub) mParent.getRootView().findViewById(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
index 3e52765..46981e7 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
@@ -23,6 +23,7 @@
 import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderProcessor;
 import org.chromium.chrome.browser.omnibox.suggestions.mostvisited.ExploreIconProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.mostvisited.MostVisitedTilesProcessor;
+import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionProcessor;
 import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionProcessor;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -99,6 +100,8 @@
         registerSuggestionProcessor(new TailSuggestionProcessor(context, host));
         registerSuggestionProcessor(new MostVisitedTilesProcessor(context, host, iconBridgeSupplier,
                 mExploreIconProvider, GlobalDiscardableReferencePool.getReferencePool()));
+        registerSuggestionProcessor(new PedalSuggestionProcessor(
+                context, host, textProvider, iconBridgeSupplier, mBookmarkState));
         registerSuggestionProcessor(new BasicSuggestionProcessor(
                 context, host, textProvider, iconBridgeSupplier, mBookmarkState));
     }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
index 77db27b0..acdf64b 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
@@ -13,7 +13,8 @@
 @IntDef({OmniboxSuggestionUiType.DEFAULT, OmniboxSuggestionUiType.EDIT_URL_SUGGESTION,
         OmniboxSuggestionUiType.ANSWER_SUGGESTION, OmniboxSuggestionUiType.ENTITY_SUGGESTION,
         OmniboxSuggestionUiType.TAIL_SUGGESTION, OmniboxSuggestionUiType.CLIPBOARD_SUGGESTION,
-        OmniboxSuggestionUiType.TILE_SUGGESTION, OmniboxSuggestionUiType.TILE_NAVSUGGEST})
+        OmniboxSuggestionUiType.TILE_SUGGESTION, OmniboxSuggestionUiType.TILE_NAVSUGGEST,
+        OmniboxSuggestionUiType.PEDAL_SUGGESTION})
 @Retention(RetentionPolicy.SOURCE)
 public @interface OmniboxSuggestionUiType {
     int DEFAULT = 0;
@@ -25,4 +26,5 @@
     int TILE_SUGGESTION = 6;
     int HEADER = 7;
     int TILE_NAVSUGGEST = 8;
+    int PEDAL_SUGGESTION = 9;
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
index c171337..d0b62df 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
@@ -22,7 +22,6 @@
 import org.chromium.components.favicon.LargeIconBridge;
 import org.chromium.components.omnibox.AutocompleteMatch;
 import org.chromium.components.omnibox.AutocompleteMatch.MatchClassification;
-import org.chromium.components.omnibox.action.OmniboxPedal;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.url.GURL;
 
@@ -97,19 +96,6 @@
     }
 
     /**
-     * Setup pedals base on the suggestion.
-     *
-     * @param model Property model to update.
-     * @param omniboxPedal OmniboxPedal for the suggestion.
-     */
-    protected void setPedal(PropertyModel model, @NonNull OmniboxPedal omniboxPedal) {
-        model.set(BaseSuggestionViewProperties.ON_PEDAL_CLICK,
-                () -> mSuggestionHost.onPedalClicked(omniboxPedal.getID()));
-
-        model.set(BaseSuggestionViewProperties.PEDAL, omniboxPedal);
-    }
-
-    /**
      * Setup action icon base on the suggestion, either show query build arrow or switch to tab.
      *
      * @param model Property model to update.
@@ -171,9 +157,6 @@
         model.set(BaseSuggestionViewProperties.ON_FOCUS_VIA_SELECTION,
                 () -> mSuggestionHost.setOmniboxEditingText(suggestion.getFillIntoEdit()));
         setCustomActions(model, null);
-        if (suggestion.getOmniboxPedal() != null) {
-            setPedal(model, suggestion.getOmniboxPedal());
-        }
     }
 
     /**
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
index 50d0f3e..c682fe4 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
@@ -11,7 +11,6 @@
 import androidx.annotation.StringRes;
 
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
-import org.chromium.components.omnibox.action.OmniboxPedal;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
@@ -79,10 +78,6 @@
     public static final WritableObjectPropertyKey<List<Action>> ACTIONS =
             new WritableObjectPropertyKey();
 
-    /** Omnibox Pedal description. */
-    public static final WritableObjectPropertyKey<OmniboxPedal> PEDAL =
-            new WritableObjectPropertyKey();
-
     /** Callback invoked when the Suggestion view is highlighted. */
     public static final WritableObjectPropertyKey<Runnable> ON_FOCUS_VIA_SELECTION =
             new WritableObjectPropertyKey<>();
@@ -95,12 +90,8 @@
     public static final WritableObjectPropertyKey<Runnable> ON_LONG_CLICK =
             new WritableObjectPropertyKey<>();
 
-    /** Callback invoked when user clicks the pedal. */
-    public static final WritableObjectPropertyKey<Runnable> ON_PEDAL_CLICK =
-            new WritableObjectPropertyKey<>();
-
-    public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] {
-            ICON, ACTIONS, PEDAL, ON_FOCUS_VIA_SELECTION, ON_CLICK, ON_LONG_CLICK, ON_PEDAL_CLICK};
+    public static final PropertyKey[] ALL_UNIQUE_KEYS =
+            new PropertyKey[] {ICON, ACTIONS, ON_FOCUS_VIA_SELECTION, ON_CLICK, ON_LONG_CLICK};
 
     public static final PropertyKey[] ALL_KEYS =
             PropertyModel.concatKeys(ALL_UNIQUE_KEYS, SuggestionCommonProperties.ALL_KEYS);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutView.java
new file mode 100644
index 0000000..62cb0af2
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutView.java
@@ -0,0 +1,52 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.base;
+
+import android.content.Context;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+
+/**
+ * SimpleVerticalLayoutView is a fast and specialized vertical layout view.
+ */
+public class SimpleVerticalLayoutView extends ViewGroup {
+    public SimpleVerticalLayoutView(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int base = getPaddingTop();
+        left = getPaddingLeft();
+        for (int index = 0; index < getChildCount(); index++) {
+            View v = getChildAt(index);
+            if (v.getVisibility() == GONE) continue;
+
+            v.layout(left, base, left + v.getMeasuredWidth(), base + v.getMeasuredHeight());
+            base += v.getMeasuredHeight();
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        final int widthPx = MeasureSpec.getSize(widthSpec);
+        final int viewWidth = widthPx - getPaddingLeft() - getPaddingRight();
+
+        int totalHeight = 0;
+        // Apply measured dimensions to all children.
+        for (int index = 0; index < getChildCount(); ++index) {
+            View v = getChildAt(index);
+            LayoutParams p = v.getLayoutParams();
+            v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            totalHeight += v.getMeasuredHeight();
+        }
+
+        setMeasuredDimension(widthPx,
+                MeasureSpec.makeMeasureSpec(
+                        totalHeight + getPaddingTop() + getPaddingBottom(), MeasureSpec.EXACTLY));
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutViewTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutViewTest.java
new file mode 100644
index 0000000..5c0dfde
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleVerticalLayoutViewTest.java
@@ -0,0 +1,119 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.base;
+
+import android.app.Activity;
+import android.content.Context;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup.LayoutParams;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * Tests for {@link SimpleVerticalLayoutView}.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class SimpleVerticalLayoutViewTest {
+    private static final int SMALL_VIEW_WIDTH = 50;
+    private static final int LARGE_VIEW_WIDTH = 120;
+    private static final int SMALL_VIEW_HEIGHT = 20;
+    private static final int LARGE_VIEW_HEIGHT = 30;
+
+    private SimpleVerticalLayoutViewForTest mView;
+    private Activity mActivity;
+
+    private View mSmallView;
+    private View mLargeView;
+
+    class SimpleVerticalLayoutViewForTest extends SimpleVerticalLayoutView {
+        SimpleVerticalLayoutViewForTest(Context context) {
+            super(context);
+        }
+
+        /**
+         * Test method to force layout update based on specified view dimensions.
+         */
+        void performLayoutForTest(int width) {
+            onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+
+            // Note: height is computed by onMeasure call.
+            final int height = getMeasuredHeight();
+            onLayout(true, 0, 0, width, height);
+        }
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mActivity = Robolectric.buildActivity(Activity.class).setup().get();
+        mView = new SimpleVerticalLayoutViewForTest(mActivity);
+
+        mSmallView = new View(mActivity);
+        mSmallView.setLayoutParams(new LayoutParams(SMALL_VIEW_WIDTH, SMALL_VIEW_HEIGHT));
+        mSmallView.setMinimumHeight(SMALL_VIEW_HEIGHT);
+        mLargeView = new View(mActivity);
+        mLargeView.setLayoutParams(new LayoutParams(LARGE_VIEW_WIDTH, LARGE_VIEW_HEIGHT));
+        mLargeView.setMinimumHeight(LARGE_VIEW_HEIGHT);
+    }
+
+    /**
+     * Perform the measure and layout pass on the SimpleVerticalLayoutView.
+     * This method sets up the basic properties of the Suggestion container, specifies height of the
+     * content view and executes the measure and layout pass.
+     */
+    private void executeLayoutTest(int containerWidth) {
+        mView.performLayoutForTest(containerWidth);
+    }
+
+    /**
+     * Confirm that specified view is positioned at specific coordinates.
+     */
+    private void verifyViewLayout(View v, int left, int top, int right, int bottom) {
+        Assert.assertEquals("left view edge", left, v.getLeft());
+        Assert.assertEquals("top view edge", top, v.getTop());
+        Assert.assertEquals("right view edge", right, v.getRight());
+        Assert.assertEquals("bottom view edge", bottom, v.getBottom());
+        Assert.assertEquals("view height", bottom - top, v.getMeasuredHeight());
+    }
+
+    /**
+     * Verify that padding are respected during layout.
+     */
+    @Test
+    public void layout_padding() {
+        final int leftPaddingWidth = 17;
+        final int rightPaddingWidth = 23;
+        final int topPaddingHeight = 13;
+        final int bottomPaddingHeight = 31;
+
+        final int overallSuggestionWidth = leftPaddingWidth + LARGE_VIEW_WIDTH + rightPaddingWidth;
+        final int largeSuggestionTop = topPaddingHeight + SMALL_VIEW_HEIGHT;
+
+        mView.setPaddingRelative(
+                leftPaddingWidth, topPaddingHeight, rightPaddingWidth, bottomPaddingHeight);
+
+        mView.addView(mSmallView);
+        mView.addView(mLargeView);
+
+        executeLayoutTest(overallSuggestionWidth);
+
+        verifyViewLayout(mSmallView, leftPaddingWidth, topPaddingHeight,
+                leftPaddingWidth + LARGE_VIEW_WIDTH, topPaddingHeight + SMALL_VIEW_HEIGHT);
+        verifyViewLayout(mLargeView, leftPaddingWidth, largeSuggestionTop,
+                leftPaddingWidth + LARGE_VIEW_WIDTH, largeSuggestionTop + LARGE_VIEW_HEIGHT);
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
new file mode 100644
index 0000000..4fbdaf4
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
@@ -0,0 +1,87 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.pedal;
+
+import android.content.Context;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.omnibox.R;
+import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
+import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
+import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
+import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor;
+import org.chromium.components.favicon.LargeIconBridge;
+import org.chromium.components.omnibox.AutocompleteMatch;
+import org.chromium.components.omnibox.action.OmniboxPedal;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * A class that handles model and view creation for the pedal omnibox suggestion.
+ */
+public class PedalSuggestionProcessor extends BasicSuggestionProcessor {
+    private final SuggestionHost mSuggestionHost;
+
+    /**
+     * @param context An Android context.
+     * @param suggestionHost A handle to the object using the suggestions.
+     */
+    public PedalSuggestionProcessor(@NonNull Context context,
+            @NonNull SuggestionHost suggestionHost,
+            @NonNull UrlBarEditingTextStateProvider editingTextProvider,
+            @NonNull Supplier<LargeIconBridge> iconBridgeSupplier,
+            @NonNull BookmarkState bookmarkState) {
+        super(context, suggestionHost, editingTextProvider, iconBridgeSupplier, bookmarkState);
+        mSuggestionHost = suggestionHost;
+    }
+
+    @Override
+    public boolean doesProcessSuggestion(AutocompleteMatch suggestion, int position) {
+        return suggestion.getOmniboxPedal() != null;
+    }
+
+    @Override
+    public int getViewTypeId() {
+        return OmniboxSuggestionUiType.PEDAL_SUGGESTION;
+    }
+
+    @Override
+    public PropertyModel createModel() {
+        return new PropertyModel(PedalSuggestionViewProperties.ALL_KEYS);
+    }
+
+    @Override
+    public void populateModel(AutocompleteMatch suggestion, PropertyModel model, int position) {
+        super.populateModel(suggestion, model, position);
+        setPedal(model, suggestion.getOmniboxPedal());
+    }
+
+    /**
+     * Setup pedals base on the suggestion.
+     *
+     * @param model Property model to update.
+     * @param omniboxPedal OmniboxPedal for the suggestion.
+     */
+    protected void setPedal(PropertyModel model, @NonNull OmniboxPedal omniboxPedal) {
+        model.set(PedalSuggestionViewProperties.PEDAL, omniboxPedal);
+        model.set(PedalSuggestionViewProperties.PEDAL_ICON, getPedalIcon(omniboxPedal));
+        model.set(PedalSuggestionViewProperties.ON_PEDAL_CLICK,
+                v -> mSuggestionHost.onPedalClicked(omniboxPedal.getID()));
+    }
+
+    /**
+     * Get default icon for pedal suggestion.
+     * @param omniboxPedal OmniboxPedal for the suggestion.
+     * @return The icon's resource id.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @DrawableRes
+    int getPedalIcon(@NonNull OmniboxPedal omniboxPedal) {
+        return R.drawable.ic_google_round;
+    }
+}
\ No newline at end of file
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java
new file mode 100644
index 0000000..0d27714
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionView.java
@@ -0,0 +1,67 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.pedal;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.chrome.browser.omnibox.R;
+import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
+import org.chromium.chrome.browser.omnibox.suggestions.base.SimpleVerticalLayoutView;
+import org.chromium.components.browser_ui.widget.chips.ChipView;
+
+/**
+ * Base layout for pedals suggestion types. This is a {@link BaseSuggestionView} with a pedal under
+ * it.
+ *
+ * @param <T> The type of View being wrapped by BaseSuggestionView.
+ */
+public class PedalSuggestionView<T extends View> extends SimpleVerticalLayoutView {
+    private final @NonNull BaseSuggestionView<T> mBaseSuggestionView;
+    private final @NonNull PedalView mPedal;
+
+    /**
+     * Constructs a new suggestion view and inflates supplied layout as the contents view.
+     *
+     * @param context The context used to construct the suggestion view.
+     * @param layoutId Layout ID to be inflated as the BaseSuggestionView.
+     */
+    public PedalSuggestionView(Context context, @LayoutRes int layoutId) {
+        super(context);
+        mBaseSuggestionView = new BaseSuggestionView<T>(context, layoutId);
+        addView(mBaseSuggestionView);
+
+        mPedal = new PedalView(getContext());
+        int pedalStartPaddingPx =
+                getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_icon_area_size);
+        int pedalEndPaddingPx =
+                getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_action_icon_width);
+        mPedal.setPaddingRelative(pedalStartPaddingPx, 0, pedalEndPaddingPx, 0);
+        addView(mPedal);
+    }
+
+    /** @return base suggestion view. */
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public BaseSuggestionView<T> getBaseSuggestionView() {
+        return mBaseSuggestionView;
+    }
+
+    /** @return The Primary TextView in the pedal view. */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public TextView getPedalTextView() {
+        return mPedal.getPedalTextView();
+    }
+
+    /** @return The {@link ChipView} in this view. */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public ChipView getPedalChipView() {
+        return mPedal.getChipView();
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java
new file mode 100644
index 0000000..03e4d61
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewBinder.java
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.pedal;
+
+import android.view.View;
+
+import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewBinder;
+import org.chromium.components.omnibox.action.OmniboxPedal;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder;
+
+/**
+ * Binds chip suggestion view properties.
+ * @param <T> The inner content view type being updated.
+ */
+public final class PedalSuggestionViewBinder<T extends View>
+        implements ViewBinder<PropertyModel, PedalSuggestionView<T>, PropertyKey> {
+    private final BaseSuggestionViewBinder<T> mBaseViewBinder;
+
+    /**
+     * Constructs a new pedal view binder.
+     *
+     * @param contentBinder The view binder for the BaseSuggestionView.
+     */
+    public PedalSuggestionViewBinder(ViewBinder<PropertyModel, T, PropertyKey> contentBinder) {
+        mBaseViewBinder = new BaseSuggestionViewBinder<T>(contentBinder);
+    }
+
+    @Override
+    public void bind(PropertyModel model, PedalSuggestionView<T> view, PropertyKey propertyKey) {
+        mBaseViewBinder.bind(model, view.getBaseSuggestionView(), propertyKey);
+
+        if (PedalSuggestionViewProperties.PEDAL == propertyKey) {
+            OmniboxPedal omniboxPedal = model.get(PedalSuggestionViewProperties.PEDAL);
+            view.getPedalTextView().setText(omniboxPedal.getHint());
+        } else if (PedalSuggestionViewProperties.PEDAL_ICON == propertyKey) {
+            view.getPedalChipView().setIcon(model.get(PedalSuggestionViewProperties.PEDAL_ICON),
+                    /*tintWithTextColor=*/false);
+        } else if (PedalSuggestionViewProperties.ON_PEDAL_CLICK == propertyKey) {
+            view.getPedalChipView().setOnClickListener(
+                    model.get(PedalSuggestionViewProperties.ON_PEDAL_CLICK));
+        }
+    }
+}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java
new file mode 100644
index 0000000..a8e22c1
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionViewProperties.java
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.pedal;
+
+import android.view.View.OnClickListener;
+
+import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
+import org.chromium.components.omnibox.action.OmniboxPedal;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
+
+/**
+ * The properties associated with rendering the pedal suggestion view.
+ */
+class PedalSuggestionViewProperties {
+    /** Omnibox Pedal description. */
+    public static final WritableObjectPropertyKey<OmniboxPedal> PEDAL =
+            new WritableObjectPropertyKey();
+
+    /** Omnibox Pedal's drawable resource id. */
+    public static final WritableIntPropertyKey PEDAL_ICON = new WritableIntPropertyKey();
+
+    /** Callback invoked when user clicks the pedal. */
+    public static final WritableObjectPropertyKey<OnClickListener> ON_PEDAL_CLICK =
+            new WritableObjectPropertyKey<>();
+
+    public static final PropertyKey[] ALL_UNIQUE_KEYS =
+            new PropertyKey[] {PEDAL, PEDAL_ICON, ON_PEDAL_CLICK};
+
+    public static final PropertyKey[] ALL_KEYS =
+            PropertyModel.concatKeys(ALL_UNIQUE_KEYS, SuggestionViewProperties.ALL_KEYS);
+}
\ No newline at end of file
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java
new file mode 100644
index 0000000..ebf699b
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalView.java
@@ -0,0 +1,61 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions.pedal;
+
+import android.content.Context;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import org.chromium.chrome.browser.omnibox.suggestions.base.SimpleHorizontalLayoutView;
+import org.chromium.components.browser_ui.widget.chips.ChipView;
+
+/**
+ * Container view for the {@link ChipView}.
+ * This view is for aligning the chip with contentview in BaseSuggestionView.
+ * Padding in front of the chip need to be same as the icon in BaseSuggestionView, and Padding at
+ * the end of the chip need to be same as the action in BaseSuggestionView.
+ */
+public class PedalView extends SimpleHorizontalLayoutView {
+    private final @NonNull ChipView mPedal;
+
+    /**
+     * Constructs a new pedal view.
+     *
+     * @param context The context used to construct the chip view.
+     */
+    public PedalView(Context context) {
+        super(context);
+
+        mPedal = new ChipView(context, null);
+        mPedal.setLayoutParams(LayoutParams.forDynamicView());
+        addView(mPedal);
+    }
+
+    @Override
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        final int widthPx = MeasureSpec.getSize(widthSpec);
+        int chipViewWidth = widthPx - getPaddingLeft() - getPaddingRight();
+
+        // Measure height of the content view given the width constraint.
+        mPedal.measure(MeasureSpec.makeMeasureSpec(chipViewWidth, MeasureSpec.AT_MOST),
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+        final int heightPx = mPedal.getMeasuredHeight();
+
+        setMeasuredDimension(widthPx,
+                MeasureSpec.makeMeasureSpec(
+                        heightPx + getPaddingTop() + getPaddingBottom(), MeasureSpec.EXACTLY));
+    }
+
+    /** @return The Primary TextView in this view. */
+    TextView getPedalTextView() {
+        return mPedal.getPrimaryTextView();
+    }
+
+    /** @return The {@link ChipView} in this view. */
+    ChipView getChipView() {
+        return mPedal;
+    }
+}
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index cdf9561e..f2768ab4 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -920,9 +920,15 @@
       <message name="IDS_PRIVACY_SANDBOX_ADD_INTEREST_BUTTON_DESCRIPTION" desc="Content description for button that adds an ad interest" translateable="false">
         Add interest?
       </message>
+      <message name="IDS_PRIVACY_SANDBOX_ADD_INTEREST_SNACKBAR" desc="Text on a snackbar after an ad personalization interest was added" translateable="false">
+        Interest added
+      </message>
       <message name="IDS_PRIVACY_SANDBOX_REMOVE_INTEREST_BUTTON_DESCRIPTION" desc="Content description for button that removes an ad interest" translateable="false">
         Remove interest?
       </message>
+      <message name="IDS_PRIVACY_SANDBOX_REMOVE_INTEREST_SNACKBAR" desc="Text on a snackbar after an ad personalization interest was removed" translateable="false">
+        Interest removed
+      </message>
        <message name="IDS_PRIVACY_SANDBOX_REMOVE_INTEREST_TITLE" desc="Title of the settings page to configure interests that were removed from ad personalization." translateable="false">
         Interests you removed
       </message>
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc b/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
index 273c493..4974608 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
+++ b/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
@@ -187,13 +187,23 @@
   if (!files_ranker_)
     return;
 
-  // The DriveQuickAccessProvider handles Drive files, so recording them here
-  // would be redundant. Filter them out by checking the file resides within the
-  // user's cryptohome.
   const auto& profile_path = profile_->GetPath();
   for (const auto& file_open : file_opens) {
-    if (profile_path.AppendRelativePath(file_open.path, nullptr))
-      files_ranker_->Use(file_open.path.value());
+    // Filter out file opens if:
+    // 1. The open event is not a kLaunch or a kOpen.
+    if (file_open.open_type != FileTasksObserver::OpenType::kLaunch &&
+        file_open.open_type != FileTasksObserver::OpenType::kOpen) {
+      continue;
+    }
+
+    // 2. The open relates to a Drive file, which is handled by another
+    // provider. Filter this out by checking if the file resides in the user's
+    // cryptohome.
+    if (!profile_path.AppendRelativePath(file_open.path, nullptr)) {
+      continue;
+    }
+
+    files_ranker_->Use(file_open.path.value());
   }
 }
 
diff --git a/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc b/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc
new file mode 100644
index 0000000..1aae09c
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc
@@ -0,0 +1,31 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/app_list/search/ranking/continue_ranker.h"
+
+#include "ash/public/cpp/app_list/app_list_types.h"
+#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
+
+namespace app_list {
+
+ContinueRanker::ContinueRanker() = default;
+ContinueRanker::~ContinueRanker() = default;
+
+void ContinueRanker::UpdateResultRanks(ResultsMap& results,
+                                       ProviderType provider) {
+  const auto it = results.find(provider);
+  DCHECK(it != results.end());
+
+  // Always rank zero-state Drive files higher than zero-state local files by
+  // giving them a higher continue_rank.
+  if (provider == ProviderType::kZeroStateFile) {
+    for (auto& result : it->second)
+      result->scoring().continue_rank = 1;
+  } else if (provider == ProviderType::kZeroStateDrive) {
+    for (auto& result : it->second)
+      result->scoring().continue_rank = 2;
+  }
+}
+
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/ranking/continue_ranker.h b/chrome/browser/ui/app_list/search/ranking/continue_ranker.h
new file mode 100644
index 0000000..f9487b2
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/ranking/continue_ranker.h
@@ -0,0 +1,28 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
+#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
+
+#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ui/app_list/search/ranking/types.h"
+
+namespace app_list {
+
+// A ranker for handling result ordering in the Continue section.
+class ContinueRanker : public Ranker {
+ public:
+  ContinueRanker();
+  ~ContinueRanker() override;
+
+  ContinueRanker(const ContinueRanker&) = delete;
+  ContinueRanker& operator=(const ContinueRanker&) = delete;
+
+  // Ranker:
+  void UpdateResultRanks(ResultsMap& results, ProviderType provider) override;
+};
+
+}  // namespace app_list
+
+#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker_delegate.cc b/chrome/browser/ui/app_list/search/ranking/ranker_delegate.cc
index 5e45f47..f61b7db6 100644
--- a/chrome/browser/ui/app_list/search/ranking/ranker_delegate.cc
+++ b/chrome/browser/ui/app_list/search/ranking/ranker_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ui/app_list/search/ranking/answer_ranker.h"
 #include "chrome/browser/ui/app_list/search/ranking/best_match_ranker.h"
+#include "chrome/browser/ui/app_list/search/ranking/continue_ranker.h"
 #include "chrome/browser/ui/app_list/search/ranking/filtering_ranker.h"
 #include "chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h"
 #include "chrome/browser/ui/app_list/search/ranking/query_highlighter.h"
@@ -68,6 +69,7 @@
   // change their scores.
   AddRanker(std::make_unique<QueryHighlighter>());
   AddRanker(std::make_unique<AnswerRanker>());
+  AddRanker(std::make_unique<ContinueRanker>());
   AddRanker(std::make_unique<FilteringRanker>());
   AddRanker(std::make_unique<RemovedResultsRanker>(
       PersistentProto<RemovedResultsProto>(
diff --git a/chrome/browser/ui/app_list/search/ranking/types.h b/chrome/browser/ui/app_list/search/ranking/types.h
index b9426c0..a8c6427 100644
--- a/chrome/browser/ui/app_list/search/ranking/types.h
+++ b/chrome/browser/ui/app_list/search/ranking/types.h
@@ -23,13 +23,20 @@
 // incrementally updated by rankers as needed. Generally, each ranker should
 // control one score.
 struct Scoring {
+  // = Members used to compute the display score of a result ===================
   bool filter = false;
-  // The rank (0, 1, 2, ...) of this result within the Best Match collection of
-  // results, or -1 if this result is not a Best Match.
-  int best_match_rank = -1;
-  double normalized_relevance = 0.0f;
+  double normalized_relevance = 0.0;
   double ftrl_result_score = 0.0;
+  // Used only for results in the Continue section. Continue results are first
+  // ordered by |continue_rank|, and then by their display score. -1 indicates
+  // this is unset.
+  int continue_rank = -1;
 
+  // = Members used for sorting in SearchController ============================
+  // The rank (0, 1, 2, ...) of this result within
+  // the Best Match collection of results, or -1 if this result is not a Best
+  // Match.
+  int best_match_rank = -1;
   // A counter for the burn-in iteration number, where 0 signifies the
   // pre-burn-in state, and 1 and above signify the post-burn-in state.
   // Incremented during the post-burn-in period each time a provider
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
index c24852d..abf9cde 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
@@ -386,6 +386,8 @@
     }
   }
 
+  // TODO(crbug.com/1258415): Refactor this lambda to be a method on the Scoring
+  // struct.
   std::sort(
       all_results.begin(), all_results.end(),
       [&](const ChromeSearchResult* a, const ChromeSearchResult* b) {
@@ -425,6 +427,9 @@
           // This happens before sorting on display_score, as a trade-off
           // between ranking accuracy and UX pop-in mitigation.
           return a->scoring().burnin_iteration < b->scoring().burnin_iteration;
+        } else if (a->scoring().continue_rank != -1 ||
+                   b->scoring().continue_rank != -1) {
+          return a->scoring().continue_rank > b->scoring().continue_rank;
         } else {
           // Lastly, sort by display score.
           return a->display_score() > b->display_score();
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
index 13edacbc..2bc9301 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
@@ -681,4 +681,30 @@
   ExpectIdOrder({"a", "b"});
 }
 
+TEST_F(SearchControllerImplNewTest, ContinueRanksDriveAboveLocal) {
+  // Use the full ranking stack.
+  search_controller_->set_ranker_delegate_for_test(
+      std::make_unique<RankerDelegate>(&profile_, search_controller_.get()));
+
+  auto drive_provider = std::make_unique<TestSearchProvider>(
+      Result::kZeroStateDrive, true, base::Seconds(0));
+  auto local_provider = std::make_unique<TestSearchProvider>(
+      Result::kZeroStateFile, true, base::Seconds(0));
+
+  drive_provider->SetNextResults(MakeResults(
+      {"drive_a", "drive_b"}, {Category::kUnknown, Category::kUnknown},
+      {-1, -1}, {0.2, 0.1}));
+  local_provider->SetNextResults(MakeResults(
+      {"local_a", "local_b"}, {Category::kUnknown, Category::kUnknown},
+      {-1, -1}, {0.5, 0.4}));
+
+  search_controller_->AddProvider(0, std::move(local_provider));
+  search_controller_->AddProvider(0, std::move(drive_provider));
+
+  search_controller_->StartZeroState(base::DoNothing(), base::Seconds(1));
+
+  Wait();
+  ExpectIdOrder({"drive_a", "drive_b", "local_a", "local_b"});
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
index faa0c41..e8bbe6f 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
@@ -102,6 +102,8 @@
     public static final int UMA_MODULE_INSTALL_FAILURE = 46;
     public static final int UMA_PRICE_TRACKING_SUCCESS = 47;
     public static final int UMA_PRICE_TRACKING_FAILURE = 48;
+    public static final int UMA_PRIVACY_SANDBOX_ADD_INTEREST = 49;
+    public static final int UMA_PRIVACY_SANDBOX_REMOVE_INTEREST = 50;
 
     private @Nullable SnackbarController mController;
     private CharSequence mText;
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index 3ccffb14..763f607 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -423,9 +423,7 @@
     DCHECK(BaseSearchProvider::ShouldPrerender(match));
     PrerenderManager::CreateForWebContents(web_contents);
     auto* prerender_manager = PrerenderManager::FromWebContents(web_contents);
-    prerender_manager->Start(
-        match.destination_url,
-        PrerenderManager::TriggerReason::kSearchSuggestion);
+    prerender_manager->StartPrerenderAutocompleteMatch(match);
   } else {
     gfx::Rect container_bounds = web_contents->GetContainerBounds();
     predictors::AutocompleteActionPredictorFactory::GetForProfile(profile_)
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 0a196e44..6acc670 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -512,9 +512,19 @@
 Profile* StartupBrowserCreator::GetPrivateProfileIfRequested(
     const base::CommandLine& command_line,
     Profile* profile) {
-  if (profiles::IsGuestModeRequested(command_line,
-                                     g_browser_process->local_state(),
-                                     /* show_warning= */ true)) {
+  bool open_guest_profile = profiles::IsGuestModeRequested(
+      command_line, g_browser_process->local_state(),
+      /* show_warning= */ true);
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (profiles::IsGuestModeEnabled()) {
+    const auto* init_params = chromeos::LacrosService::Get()->init_params();
+    open_guest_profile =
+        open_guest_profile ||
+        init_params->initial_browser_action ==
+            crosapi::mojom::InitialBrowserAction::kOpenGuestWindow;
+  }
+#endif
+  if (open_guest_profile) {
     profile = g_browser_process->profile_manager()->GetProfile(
         ProfileManager::GetGuestProfilePath());
     profile = profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
index bbfc263d..9e0ea44 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -125,25 +125,6 @@
        profile_color});
 }
 
-void ExpectSyncAborted(Profile* profile) {
-  ProfileAttributesEntry* entry =
-      g_browser_process->profile_manager()
-          ->GetProfileAttributesStorage()
-          .GetProfileAttributesWithPath(profile->GetPath());
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile);
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // TODO(https://crbug.com/1217645): Add support for signed out / non-syncing
-  // profiles. For the time being, it enables sync but disables all datatypes.
-  EXPECT_TRUE(entry->IsAuthenticated());
-  EXPECT_TRUE(sync_service->HasSyncConsent());
-  EXPECT_FALSE(sync_service->GetUserSettings()->IsSyncEverythingEnabled());
-#else
-  EXPECT_FALSE(entry->IsAuthenticated());
-  EXPECT_FALSE(sync_service->HasSyncConsent());
-#endif
-}
-
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 
 class FakeAccountManagerUIAddAccountDialogWaiter
@@ -632,7 +613,10 @@
   EXPECT_FALSE(entry->IsEphemeral());
   EXPECT_EQ(entry->GetLocalProfileName(), u"Joe");
 
-  ExpectSyncAborted(profile_being_created);
+  syncer::SyncService* sync_service =
+      SyncServiceFactory::GetForProfile(profile_being_created);
+  EXPECT_FALSE(entry->IsAuthenticated());
+  EXPECT_FALSE(sync_service->HasSyncConsent());
   EXPECT_EQ(ThemeServiceFactory::GetForProfile(profile_being_created)
                 ->GetAutogeneratedThemeColor(),
             kProfileColor);
@@ -695,7 +679,10 @@
   EXPECT_FALSE(entry->IsEphemeral());
   EXPECT_EQ(entry->GetLocalProfileName(), u"Joe");
 
-  ExpectSyncAborted(profile_being_created);
+  syncer::SyncService* sync_service =
+      SyncServiceFactory::GetForProfile(profile_being_created);
+  EXPECT_FALSE(entry->IsAuthenticated());
+  EXPECT_FALSE(sync_service->HasSyncConsent());
   EXPECT_EQ(ThemeServiceFactory::GetForProfile(profile_being_created)
                 ->GetAutogeneratedThemeColor(),
             kProfileColor);
@@ -806,7 +793,10 @@
   EXPECT_FALSE(entry->IsEphemeral());
   EXPECT_EQ(entry->GetLocalProfileName(), u"Joe");
 
-  ExpectSyncAborted(profile_being_created);
+  syncer::SyncService* sync_service =
+      SyncServiceFactory::GetForProfile(profile_being_created);
+  EXPECT_FALSE(entry->IsAuthenticated());
+  EXPECT_FALSE(sync_service->HasSyncConsent());
   EXPECT_EQ(ThemeServiceFactory::GetForProfile(profile_being_created)
                 ->GetAutogeneratedThemeColor(),
             kDifferentProfileColor);
@@ -937,7 +927,10 @@
   // a profile name.
   EXPECT_EQ(entry->GetLocalProfileName(), u"joe.consumer@gmail.com");
 
-  ExpectSyncAborted(profile_being_created);
+  syncer::SyncService* sync_service =
+      SyncServiceFactory::GetForProfile(profile_being_created);
+  EXPECT_FALSE(entry->IsAuthenticated());
+  EXPECT_FALSE(sync_service->HasSyncConsent());
   EXPECT_EQ(ThemeServiceFactory::GetForProfile(profile_being_created)
                 ->GetAutogeneratedThemeColor(),
             kProfileColor);
@@ -1314,7 +1307,10 @@
   EXPECT_FALSE(entry->IsEphemeral());
   EXPECT_EQ(entry->GetLocalProfileName(), u"enterprise.com");
 
-  ExpectSyncAborted(profile_being_created);
+  syncer::SyncService* sync_service =
+      SyncServiceFactory::GetForProfile(profile_being_created);
+  EXPECT_FALSE(entry->IsAuthenticated());
+  EXPECT_FALSE(sync_service->HasSyncConsent());
   EXPECT_EQ(ThemeServiceFactory::GetForProfile(profile_being_created)
                 ->GetAutogeneratedThemeColor(),
             kProfileColor);
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index ba3acd7..73f4e45f 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -308,7 +308,6 @@
 bool ShouldPrepareForRecovery(const AccountId& account_id) {
   if (!account_id.is_valid())
     return false;
-  int reauth_reason;
   // Cryptohome recovery is probably needed when password is entered incorrectly
   // for many times or password changed.
   // TODO(b/197615068): Add metric to record the number of times we prepared for
@@ -320,8 +319,9 @@
       ash::ReauthReason::PASSWORD_UPDATE_SKIPPED,
   };
   user_manager::KnownUser known_user(g_browser_process->local_state());
-  return known_user.FindReauthReason(account_id, &reauth_reason) &&
-         base::Contains(kPossibleReasons, reauth_reason);
+  absl::optional<int> reauth_reason = known_user.FindReauthReason(account_id);
+  return reauth_reason.has_value() &&
+         base::Contains(kPossibleReasons, reauth_reason.value());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index c0bd9fa..bf8c104a 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -799,23 +799,15 @@
 void SiteSettingsHandler::HandleClearUnpartitionedUsage(
     const base::ListValue* args) {
   CHECK_EQ(1U, args->GetList().size());
-  const std::string& origin = args->GetList()[0].GetString();
-  GURL url(origin);
-  if (!url.is_valid())
+  const std::string& origin_string = args->GetList()[0].GetString();
+  auto origin = url::Origin::Create(GURL(origin_string));
+  if (origin.opaque())
     return;
   AllowJavascript();
 
-  RemoveMatchingNodes(cookies_tree_model_.get(), origin, absl::nullopt);
+  RemoveMatchingNodes(cookies_tree_model_.get(), origin_string, absl::nullopt);
 
-  // TODO(crbug.com/1271155, crbug.com/1268626): This is a temporary hack while
-  // the CookiesTreeModel is deprecated. Currently cookies will fail to be
-  // deleted if only cookies exist and the origin's scheme is 'https'. The
-  // origin's scheme in the cookie node is `http` whereas the expected scheme
-  // for the origin is `https`, so we cannot use the cookie node origin to
-  // remove site client hints data before the issue is resolved.
-  HostContentSettingsMapFactory::GetForProfile(profile_)
-      ->SetWebsiteSettingDefaultScope(
-          url, GURL(), ContentSettingsType::CLIENT_HINTS, base::Value());
+  RemoveNonTreeModelData({origin});
 }
 
 void SiteSettingsHandler::HandleClearPartitionedUsage(
@@ -1737,6 +1729,29 @@
 
   AllowJavascript();
   RemoveMatchingNodes(cookies_tree_model_.get(), absl::nullopt, etld_plus1);
+
+  // Retrieve all of the origin entries grouped under this eTLD + 1.
+  std::vector<url::Origin> affected_origins;
+  for (const auto& origin_is_partitioned : all_sites_map_[etld_plus1]) {
+    // Ignore entries which are partitioned, as no non-cookie tree storage is
+    // partitioned.
+    if (origin_is_partitioned.second)
+      continue;
+
+    affected_origins.emplace_back(
+        url::Origin::Create(GURL(origin_is_partitioned.first)));
+  }
+
+  // Cookies may have associated with the entry for the eTLD+1 itself.
+  // As per the logic in CreateOrAppendSiteGroupEntry, this will only occur
+  // if the existing entry was https, otherwise a new http entry would be
+  // created. Hence, we need only additionally include the HTTPS version of
+  // the eTLD+1 as an origin.
+  std::string https_url = std::string(url::kHttpsScheme) +
+                          url::kStandardSchemeSeparator + etld_plus1 + "/";
+  affected_origins.emplace_back(url::Origin::Create(GURL(https_url)));
+
+  RemoveNonTreeModelData(affected_origins);
 }
 
 void SiteSettingsHandler::HandleRecordAction(const base::ListValue* args) {
@@ -1749,6 +1764,19 @@
   LogAllSitesAction(static_cast<AllSitesAction2>(action));
 }
 
+void SiteSettingsHandler::RemoveNonTreeModelData(
+    const std::vector<url::Origin>& origins) {
+  // TODO(crbug.com/1268626): Remove client hint information, which cannot be
+  // associated with Cookie node information as the scheme in the cookie node
+  // may not match due to HTTP / HTTPS distinction issues.
+  for (const auto& origin : origins) {
+    HostContentSettingsMapFactory::GetForProfile(profile_)
+        ->SetWebsiteSettingDefaultScope(origin.GetURL(), GURL(),
+                                        ContentSettingsType::CLIENT_HINTS,
+                                        base::Value());
+  }
+}
+
 void SiteSettingsHandler::SetCookiesTreeModelForTesting(
     std::unique_ptr<CookiesTreeModel> cookies_tree_model) {
   cookies_tree_model_ = std::move(cookies_tree_model);
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h
index 235a454..aa8865f 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -129,8 +129,7 @@
                            HandleClearEtldPlus1DataAndCookies);
   FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
                            HandleClearUnpartitionedUsage);
-  FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
-                           ClearUnpartitionedClearsHints);
+  FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ClearClientHints);
   FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
                            HandleClearPartitionedUsage);
   FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieSettingDescription);
@@ -271,6 +270,12 @@
   // Record metrics for actions on All Sites Page.
   void HandleRecordAction(const base::ListValue* args);
 
+  // Provides an opportunity for site data which is not integrated into the
+  // tree model to be removed when entries for |origins| are removed.
+  // TODO(crbug.com/1271155): This function is a temporary hack while the
+  // CookiesTreeModel is deprecated.
+  void RemoveNonTreeModelData(const std::vector<url::Origin>& origins);
+
   void SetCookiesTreeModelForTesting(
       std::unique_ptr<CookiesTreeModel> cookies_tree_model);
 
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index 1c05a761..6855535 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -2615,12 +2615,14 @@
   EXPECT_TRUE(cookie->IsPartitioned());
 }
 
-TEST_F(SiteSettingsHandlerTest, ClearUnpartitionedClearsHints) {
-  // Confirm that when the user clears unpartitioned storage, client hints
-  // are also cleared.
+TEST_F(SiteSettingsHandlerTest, ClearClientHints) {
+  // Confirm that when the user clears unpartitioned storage, or the eTLD+1
+  // group, client hints are also cleared.
   SetUpCookiesTreeModel();
+  handler()->OnStorageFetched();
 
-  GURL hosts[] = {GURL("https://example.com/"), GURL("https://google.com/")};
+  GURL hosts[] = {GURL("https://example.com/"), GURL("https://www.example.com"),
+                  GURL("https://google.com/"), GURL("https://www.google.com/")};
 
   HostContentSettingsMap* host_content_settings_map =
       HostContentSettingsMapFactory::GetForProfile(profile());
@@ -2645,16 +2647,40 @@
         client_hints_dictionary.Clone());
   }
 
-  // Clear unpartitioned usage data.
+  // Clear at the eTLD+1 level and ensure affected origins are cleared.
   base::Value args(base::Value::Type::LIST);
-  args.Append("https://example.com/");
+  args.Append("example.com");
+  handler()->HandleClearEtldPlus1DataAndCookies(
+      &base::Value::AsListValue(args));
+  host_content_settings_map->GetSettingsForOneType(
+      ContentSettingsType::CLIENT_HINTS, &client_hints_settings);
+  EXPECT_EQ(2U, client_hints_settings.size());
+
+  EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(hosts[2]),
+            client_hints_settings.at(0).primary_pattern);
+  EXPECT_EQ(ContentSettingsPattern::Wildcard(),
+            client_hints_settings.at(0).secondary_pattern);
+  EXPECT_EQ(client_hints_dictionary, client_hints_settings.at(0).setting_value);
+
+  EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(hosts[3]),
+            client_hints_settings.at(1).primary_pattern);
+  EXPECT_EQ(ContentSettingsPattern::Wildcard(),
+            client_hints_settings.at(1).secondary_pattern);
+  EXPECT_EQ(client_hints_dictionary, client_hints_settings.at(1).setting_value);
+
+  // Clear unpartitioned usage data, which should only affect the specific
+  // origin.
+  args.ClearList();
+  args.Append("https://google.com/");
   handler()->HandleClearUnpartitionedUsage(&base::Value::AsListValue(args));
 
   // Validate the client hint has been cleared.
   host_content_settings_map->GetSettingsForOneType(
       ContentSettingsType::CLIENT_HINTS, &client_hints_settings);
   EXPECT_EQ(1U, client_hints_settings.size());
-  EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(hosts[1]),
+
+  // www.google.com should be the only remainining entry.
+  EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard(hosts[3]),
             client_hints_settings.at(0).primary_pattern);
   EXPECT_EQ(ContentSettingsPattern::Wildcard(),
             client_hints_settings.at(0).secondary_pattern);
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index 1ffd426..49cd844 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -26,6 +26,7 @@
 #include "components/consent_auditor/consent_auditor.h"
 #include "components/signin/public/base/avatar_icon_util.h"
 #include "components/signin/public/base/consent_level.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -101,8 +102,7 @@
 
 void SyncConfirmationHandler::HandleUndo(const base::ListValue* args) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // TODO(crbug.com/1263553): Remove once unconsented profiles are supported.
-  NOTIMPLEMENTED() << "Unconsented profiles are not supported yet";
+  DCHECK(base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles));
 #endif
   did_user_explicitly_interact_ = true;
   CloseModalSigninWindow(LoginUIService::ABORT_SYNC);
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
index 999de7c..c8bb1c4 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/scoped_observation.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/metrics/user_action_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/consent_auditor/consent_auditor_factory.h"
 #include "chrome/browser/consent_auditor/consent_auditor_test_utils.h"
@@ -31,6 +32,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/consent_auditor/fake_consent_auditor.h"
 #include "components/signin/public/base/avatar_icon_util.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_web_ui.h"
 
@@ -211,6 +213,11 @@
   base::HistogramTester histogram_tester_;
   std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
       identity_test_env_adaptor_;
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  base::test::ScopedFeatureList feature_list_{
+      switches::kLacrosNonSyncingProfiles};
+#endif
 };
 
 const char SyncConfirmationHandlerTest::kConsentText1[] = "consentText1";
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index 25845c2..91a09eb4 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -24,6 +24,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/signin_resources.h"
 #include "components/signin/public/base/avatar_icon_util.h"
+#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui.h"
@@ -46,6 +47,12 @@
              : GetDefaultProfileThemeColors(dark_mode);
 }
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+bool SyncForced() {
+  return !base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles);
+}
+#endif
+
 }  // namespace
 
 SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
@@ -102,27 +109,20 @@
     absl::optional<SkColor> profile_creation_flow_color,
     DesignVersion design,
     bool is_modal_dialog) {
-  AddStringResource(source, "syncConfirmationTitle",
+  int title_id = IDS_SYNC_CONFIRMATION_TITLE;
+  int info_title_id = IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE;
+  int confirm_label_id = IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL;
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-                    IDS_SYNC_CONFIRMATION_TITLE_LACROS
-#else
-                    IDS_SYNC_CONFIRMATION_TITLE
+  if (SyncForced()) {
+    title_id = IDS_SYNC_CONFIRMATION_TITLE_LACROS;
+    info_title_id = IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE_LACROS;
+    confirm_label_id = IDS_DONE;
+  }
 #endif
-  );
-  AddStringResource(source, "syncConfirmationSyncInfoTitle",
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-                    IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE_LACROS
-#else
-                    IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE
-#endif
-  );
-  AddStringResource(source, "syncConfirmationConfirmLabel",
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-                    IDS_DONE
-#else
-                    IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL
-#endif
-  );
+  AddStringResource(source, "syncConfirmationTitle", title_id);
+  AddStringResource(source, "syncConfirmationSyncInfoTitle", info_title_id);
+  AddStringResource(source, "syncConfirmationConfirmLabel", confirm_label_id);
+
   AddStringResource(source, "syncConfirmationSyncInfoDesc",
                     IDS_SYNC_CONFIRMATION_SYNC_INFO_DESC);
   AddStringResource(source, "syncConfirmationSettingsInfo",
@@ -138,6 +138,13 @@
 
   source->AddBoolean("isModalDialog", is_modal_dialog);
 
+  bool sync_forced = false;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (SyncForced())
+    sync_forced = true;
+#endif
+  source->AddBoolean("syncForced", sync_forced);
+
   switch (design) {
     case DesignVersion::kMonotone: {
       source->AddString("accountPictureUrl",
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
index eea5fb3..4c919c3 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
@@ -11,6 +11,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/webui/signin/signin_web_dialog_ui.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Browser;
 class Profile;
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc
index 022a8d9..d7a5a57 100644
--- a/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc
+++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc
@@ -597,21 +597,6 @@
       break;
     }
     case LoginUIService::ABORT_SYNC: {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-      // TODO(crbug.com/1263553): Support truly disabling sync on lacros. Before
-      // this is done, all data types get disabled, instead. This is only
-      // exposed to tests as the "No" button is hidden until the full support is
-      // implemented.
-      syncer::SyncService* sync_service = GetSyncService();
-      if (sync_service) {
-        sync_service->GetUserSettings()->SetSelectedTypes(
-            /*sync_everything=*/false,
-            /*types=*/{});
-        sync_service->GetUserSettings()->SetFirstSetupComplete(
-            syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
-      }
-      break;
-#else
       auto* primary_account_mutator =
           identity_manager_->GetPrimaryAccountMutator();
       DCHECK(primary_account_mutator);
@@ -620,7 +605,6 @@
           signin_metrics::SignoutDelete::kIgnoreMetric);
       AbortAndDelete();
       return;
-#endif
     }
     // No explicit action when the ui gets closed. If the embedder wants the
     // helper to abort sync in this case, it must redirect this action to
@@ -669,8 +653,12 @@
 }
 
 void TurnSyncOnHelper::AbortAndDelete() {
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
   if (signin_aborted_mode_ == SigninAbortedMode::REMOVE_ACCOUNT) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+    // TODO(https://crbug.com/1260291): Implement or make sure this is
+    // unreachable on lacros.
+    NOTIMPLEMENTED() << "REMOVE_ACCOUNT mode is not supported on lacros";
+#endif
     policy::UserPolicySigninServiceFactory::GetForProfile(profile_)
         ->ShutdownUserCloudPolicyManager();
     // Revoke the token, and the AccountReconcilor and/or the Gaia server will
@@ -681,11 +669,6 @@
         signin_metrics::SourceForRefreshTokenOperation::
             kTurnOnSyncHelper_Abort);
   }
-#else
-  // TODO(https://crbug.com/1260291): Implement on Lacros.
-  NOTIMPLEMENTED()
-      << "Profiles without accounts are not yet supported on lacros.";
-#endif
 
   delete this;
 }
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
index 378dcb0..9c9cee1 100644
--- a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
@@ -351,38 +351,17 @@
   }
 
   void SetExpectationsForSyncAborted() {
-// TODO(crbug.com/1263553): Get rid of the lacros special casing once sync
-// disabled is fully supported on lacros.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-    EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-                SetSelectedTypes(/*sync_everything=*/false,
-                                 /*types=*/syncer::UserSelectableTypeSet()));
-    EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-                SetFirstSetupComplete(
-                    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW));
-#else
     EXPECT_CALL(
         *GetMockSyncService()->GetMockUserSettings(),
         SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
         .Times(0);
-#endif
   }
 
   void CheckSyncAborted(bool has_primary_account) {
-// TODO(crbug.com/1263553): Get rid of the lacros special casing once sync
-// disabled is fully supported on lacros.
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-    // Disabling all data types is asserted in
-    // `SetExpectationsForSyncAborted()`.
-    EXPECT_TRUE(
-        identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
-    EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id()));
-#else
     EXPECT_FALSE(
         identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
     EXPECT_EQ(has_primary_account,
               identity_manager()->HasAccountWithRefreshToken(account_id()));
-#endif
   }
 
   void CheckDelegateCalls() {
diff --git a/chrome/browser/web_applications/adjustments/link_capturing_pref_migration.h b/chrome/browser/web_applications/adjustments/link_capturing_pref_migration.h
index c5c91df..b502cb8 100644
--- a/chrome/browser/web_applications/adjustments/link_capturing_pref_migration.h
+++ b/chrome/browser/web_applications/adjustments/link_capturing_pref_migration.h
@@ -37,8 +37,6 @@
   base::ScopedObservation<apps::AppRegistryCache,
                           apps::AppRegistryCache::Observer>
       scoped_observation_{this};
-
-  base::WeakPtrFactory<LinkCapturingPrefMigration> weak_factory_{this};
 };
 
 }  // namespace web_app
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 5fcdc47c..60444701 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1643759421-55c7d0c7dd4f604694c3cb58594ab177b31274a7.profdata
+chrome-linux-main-1643780792-8b5eab08c254565c4e2a2fa4e0dc249015b9d700.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index d284ed77..df19cfe 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1643759421-ab19e24cd8ca31ce8d4b104dee13ae557d24228f.profdata
+chrome-mac-arm-main-1643780792-92f3af9610fb789dd009ac1fec97c2184824a3a7.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 1bca107..1679248 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1643759421-1eaad10266535163555c4795e1a1d093e9cf157b.profdata
+chrome-mac-main-1643780792-d79021a68ac956c11aa11d8b3831857387c0bc36.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 13b7596c..e699445e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1643770456-4cfbf323095e077e80152739699ea1df20cea2a3.profdata
+chrome-win32-main-1643791162-ef2e5882a0d644f0787b5ee3fc0e09c3be07dc46.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 68f9bbf..825c7b5a 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1643738083-fb89b792bce03e0c87450bbcab719c1057e98b66.profdata
+chrome-win64-main-1643791162-3bc6fc5f25941e3e7a74d217989f8e8b5e82c18d.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 96bea49..30d48d5 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -807,6 +807,9 @@
       "../browser/metrics/ukm_browsertest.cc",
       "../browser/net/cert_verify_proc_browsertest.cc",
       "../browser/page_load_metrics/observers/ad_metrics/ad_density_intervention_android_browsertest.cc",
+      "../browser/password_manager/android/password_manager_android_browsertest.cc",
+      "../browser/password_manager/passwords_navigation_observer.cc",
+      "../browser/password_manager/passwords_navigation_observer.h",
       "../browser/policy/policy_prefs_browsertest.cc",
       "../browser/profiles/profile_browsertest_android.cc",
       "../browser/safe_browsing/test_safe_browsing_database_helper.cc",
@@ -831,6 +834,7 @@
       "//components/messages/android:feature_flags",
       "//components/messages/android/test:test_support_cpp",
       "//components/messages/android/test:test_support_java",
+      "//components/password_manager/content/browser:browser",
       "//components/policy:chrome_settings_proto_generated_compile",
       "//components/policy/core/browser:test_support",
       "//components/safe_browsing/content/renderer/phishing_classifier:phishing_classifier",
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn
index bb4fce61..61db1a6 100644
--- a/chrome/test/data/webui/new_tab_page/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -48,18 +48,9 @@
     "modules:module_registry_test",
     "modules:module_wrapper_test",
     "modules:modules_test",
-    "modules/cart:module_test",
-    "modules/cart_v2:module_test",
-    "modules/drive:module_test",
-    "modules/drive_v2:module_test",
-    "modules/recipes_v2:module_test",
-    "modules/task_module:module_test",
   ]
   if (!is_official_build) {
-    deps += [
-      "modules/dummy_v2:module_test",
-      "modules/photos:module_test",
-    ]
+    deps += [ "modules/dummy_v2:module_test" ]
   }
 }
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/cart/BUILD.gn
deleted file mode 100644
index f33bb86..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/cart/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:metrics_test_support",
-    "../..:test_support",
-    "//chrome/browser/cart:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart_v2/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/cart_v2/BUILD.gn
deleted file mode 100644
index f33bb86..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/cart_v2/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:metrics_test_support",
-    "../..:test_support",
-    "//chrome/browser/cart:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/drive/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/drive/BUILD.gn
deleted file mode 100644
index 0015cc54..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/drive/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:test_support",
-    "//chrome/browser/new_tab_page/modules/drive:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/drive_v2/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/drive_v2/BUILD.gn
deleted file mode 100644
index 0015cc54..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/drive_v2/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:test_support",
-    "//chrome/browser/new_tab_page/modules/drive:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/photos/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/photos/BUILD.gn
deleted file mode 100644
index 3f3ae94b..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/photos/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:metrics_test_support",
-    "../..:test_support",
-    "//chrome/browser/new_tab_page/modules/photos:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/recipes_v2/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/recipes_v2/BUILD.gn
deleted file mode 100644
index cbab02e9..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/recipes_v2/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:test_support",
-    "//chrome/browser/new_tab_page/modules/task_module:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//ui/webui/resources/js:assert.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/new_tab_page/modules/task_module/BUILD.gn b/chrome/test/data/webui/new_tab_page/modules/task_module/BUILD.gn
deleted file mode 100644
index 1b40c89..0000000
--- a/chrome/test/data/webui/new_tab_page/modules/task_module/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("module_test") {
-  deps = [
-    "../..:test_support",
-    "//chrome/browser/new_tab_page/modules/task_module:mojo_bindings_webui_js",
-    "//chrome/browser/resources/new_tab_page",
-    "//chrome/test/data/webui:chai_assert",
-    "//chrome/test/data/webui:test_browser_proxy",
-    "//chrome/test/data/webui:test_util",
-    "//ui/webui/resources/js:assert.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/settings/privacy_review_page_test.ts b/chrome/test/data/webui/settings/privacy_review_page_test.ts
index a5e14050..31cb573f 100644
--- a/chrome/test/data/webui/settings/privacy_review_page_test.ts
+++ b/chrome/test/data/webui/settings/privacy_review_page_test.ts
@@ -6,9 +6,10 @@
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {CookiePrimarySetting, PrivacyReviewHistorySyncFragmentElement, PrivacyReviewStep, PrivacyReviewWelcomeFragmentElement, SafeBrowsingSetting, SettingsPrivacyReviewPageElement, SettingsRadioGroupElement} from 'chrome://settings/lazy_load.js';
-import {MetricsBrowserProxyImpl, PrivacyGuideInteractions, Router, routes, StatusAction, SyncBrowserProxyImpl, SyncPrefs, syncPrefsIndividualDataTypes, SyncStatus} from 'chrome://settings/settings.js';
+import {MetricsBrowserProxyImpl, PrivacyGuideInteractions, PrivacyGuideSettingsStates, Router, routes, StatusAction, SyncBrowserProxyImpl, SyncPrefs, syncPrefsIndividualDataTypes, SyncStatus} from 'chrome://settings/settings.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise, flushTasks, isChildVisible} from 'chrome://webui-test/test_util.js';
+import {getSyncAllPrefs} from './sync_test_util.js';
 
 import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js';
 import {TestSyncBrowserProxy} from './test_sync_browser_proxy.js';
@@ -44,6 +45,12 @@
           value: false,
         },
       },
+      url_keyed_anonymized_data_collection: {
+        enabled: {
+          type: chrome.settingsPrivate.PrefType.BOOLEAN,
+          value: true,
+        },
+      },
       generated: {
         cookie_primary_setting: {
           type: chrome.settingsPrivate.PrefType.NUMBER,
@@ -103,9 +110,23 @@
   }
 
   /**
-   * Fire a sync status changed event and flush the UI.
+   * Set all relevant sync status and fire a changed event and flush the UI.
    */
-  function setSyncEnabled(syncOn: boolean) {
+  function setupSync({
+    syncOn,
+    syncAllDataTypes,
+    typedUrlsSynced,
+  }: {
+    syncAllDataTypes: boolean,
+    typedUrlsSynced: boolean,
+    syncOn: boolean,
+  }) {
+    if (syncAllDataTypes) {
+      assertTrue(typedUrlsSynced);
+    }
+    if (typedUrlsSynced) {
+      assertTrue(syncOn);
+    }
     syncBrowserProxy.testSyncStatus = {
       signedIn: syncOn,
       hasError: false,
@@ -113,6 +134,12 @@
     };
     webUIListenerCallback(
         'sync-status-changed', syncBrowserProxy.testSyncStatus);
+
+    const event = getSyncAllPrefs();
+    // Overwrite datatypes needed in tests.
+    event.syncAllDataTypes = syncAllDataTypes;
+    event.typedUrlsSynced = typedUrlsSynced;
+    webUIListenerCallback('sync-prefs-changed', event);
     flush();
   }
 
@@ -301,6 +328,135 @@
     assertStepIndicatorModel(activeIndex);
   }
 
+  async function assertMsbbMetrics({
+    msbbStartOn,
+    changeSetting,
+    expectedMetric,
+  }: {
+    msbbStartOn: boolean,
+    changeSetting: boolean,
+    expectedMetric: PrivacyGuideSettingsStates,
+  }) {
+    page.setPrefValue(
+        'url_keyed_anonymized_data_collection.enabled', msbbStartOn);
+    flush();
+    navigateToStep(PrivacyReviewStep.MSBB);
+    assertMsbbCardVisible();
+
+    if (changeSetting) {
+      page.shadowRoot!.querySelector('#' + PrivacyReviewStep.MSBB)!.shadowRoot!
+          .querySelector<HTMLElement>('#urlCollectionToggle')!.click();
+      flush();
+    }
+
+    page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click();
+    flush();
+
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideSettingsStatesHistogram');
+    assertEquals(result, expectedMetric);
+  }
+
+  async function assertHistorySyncMetrics({
+    historySyncStartOn,
+    changeSetting,
+    expectedMetric,
+  }: {
+    historySyncStartOn: boolean,
+    changeSetting: boolean,
+    expectedMetric: PrivacyGuideSettingsStates,
+  }) {
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: historySyncStartOn,
+      typedUrlsSynced: historySyncStartOn,
+    });
+    navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
+    assertHistorySyncCardVisible();
+
+    if (changeSetting) {
+      page.shadowRoot!.querySelector('#' + PrivacyReviewStep.HISTORY_SYNC)!
+          .shadowRoot!.querySelector<HTMLElement>('#historyToggle')!.click();
+      flush();
+    }
+
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideSettingsStatesHistogram');
+    assertEquals(result, expectedMetric);
+  }
+
+  async function assertSafeBrowsingMetrics({
+    safeBrowsingStartsEnhanced,
+    changeSetting,
+    expectedMetric,
+  }: {
+    safeBrowsingStartsEnhanced: boolean,
+    changeSetting: boolean,
+    expectedMetric: PrivacyGuideSettingsStates,
+  }) {
+    const safeBrowsingStartState = safeBrowsingStartsEnhanced ?
+        SafeBrowsingSetting.ENHANCED :
+        SafeBrowsingSetting.STANDARD;
+    page.setPrefValue('generated.safe_browsing', safeBrowsingStartState);
+    flush();
+    navigateToStep(PrivacyReviewStep.SAFE_BROWSING);
+    assertSafeBrowsingCardVisible();
+
+    if (changeSetting) {
+      page.shadowRoot!.querySelector(
+                          '#' + PrivacyReviewStep.SAFE_BROWSING)!.shadowRoot!
+          .querySelector<HTMLElement>(
+              safeBrowsingStartsEnhanced ?
+                  '#safeBrowsingRadioStandard' :
+                  '#safeBrowsingRadioEnhanced')!.click();
+      flush();
+    }
+
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideSettingsStatesHistogram');
+    assertEquals(result, expectedMetric);
+  }
+
+  async function assertCookieMetrics({
+    cookieStartsBlock3PIncognito,
+    changeSetting,
+    expectedMetric,
+  }: {
+    cookieStartsBlock3PIncognito: boolean,
+    changeSetting: boolean,
+    expectedMetric: PrivacyGuideSettingsStates,
+  }) {
+    const cookieStartState = cookieStartsBlock3PIncognito ?
+        CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO :
+        CookiePrimarySetting.BLOCK_THIRD_PARTY;
+    page.setPrefValue('generated.cookie_primary_setting', cookieStartState);
+    flush();
+    navigateToStep(PrivacyReviewStep.COOKIES);
+    assertCookiesCardVisible();
+
+    if (changeSetting) {
+      page.shadowRoot!.querySelector(
+                          '#' + PrivacyReviewStep.COOKIES)!.shadowRoot!
+          .querySelector<HTMLElement>(
+              cookieStartsBlock3PIncognito ? '#block3P' :
+                                             '#block3PIncognito')!.click();
+      flush();
+    }
+
+    page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
+    flush();
+
+    const result = await testMetricsBrowserProxy.whenCalled(
+        'recordPrivacyGuideSettingsStatesHistogram');
+    assertEquals(result, expectedMetric);
+  }
+
   test('startPrivacyReview', function() {
     // Navigating to the privacy review without a step parameter navigates to
     // the welcome card.
@@ -333,7 +489,11 @@
         await testMetricsBrowserProxy.whenCalled('recordAction');
     assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickWelcome');
 
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     assertMsbbCardVisible();
   });
 
@@ -350,9 +510,45 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickMSBB');
   });
 
+  test('msbbMetricsOnToOn', async function() {
+    await assertMsbbMetrics({
+      msbbStartOn: true,
+      changeSetting: false,
+      expectedMetric: PrivacyGuideSettingsStates.MSBB_ON_TO_ON
+    });
+  });
+
+  test('msbbMetricsOnToOff', async function() {
+    await assertMsbbMetrics({
+      msbbStartOn: true,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.MSBB_ON_TO_OFF
+    });
+  });
+
+  test('msbbMetricsOffToOn', async function() {
+    await assertMsbbMetrics({
+      msbbStartOn: false,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.MSBB_OFF_TO_ON
+    });
+  });
+
+  test('msbbMetricsOffToOff', async function() {
+    await assertMsbbMetrics({
+      msbbStartOn: false,
+      changeSetting: false,
+      expectedMetric: PrivacyGuideSettingsStates.MSBB_OFF_TO_OFF
+    });
+  });
+
   test('msbbForwardNavigationSyncOn', async function() {
     navigateToStep(PrivacyReviewStep.MSBB);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     assertMsbbCardVisible();
 
     page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
@@ -369,7 +565,11 @@
 
   test('msbbForwardNavigationSyncOff', function() {
     navigateToStep(PrivacyReviewStep.MSBB);
-    setSyncEnabled(false);
+    setupSync({
+      syncOn: false,
+      syncAllDataTypes: false,
+      typedUrlsSynced: false,
+    });
     assertMsbbCardVisible();
 
     page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click();
@@ -378,7 +578,11 @@
 
   test('historySyncBackNavigation', async function() {
     navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     assertHistorySyncCardVisible();
 
     page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click();
@@ -389,19 +593,68 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickHistorySync');
   });
 
+  test('historySyncOnToOn', async function() {
+    await assertHistorySyncMetrics({
+      historySyncStartOn: true,
+      changeSetting: false,
+      expectedMetric: PrivacyGuideSettingsStates.HISTORY_SYNC_ON_TO_ON
+    });
+  });
+
+  test('historySyncOnToOff', async function() {
+    await assertHistorySyncMetrics({
+      historySyncStartOn: true,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.HISTORY_SYNC_ON_TO_OFF
+    });
+  });
+
+  test('historySyncOffToOn', async function() {
+    await assertHistorySyncMetrics({
+      historySyncStartOn: false,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.HISTORY_SYNC_OFF_TO_ON
+    });
+  });
+
+  test('historySyncOffToOff', async function() {
+    await assertHistorySyncMetrics({
+      historySyncStartOn: false,
+      changeSetting: false,
+      expectedMetric: PrivacyGuideSettingsStates.HISTORY_SYNC_OFF_TO_OFF
+    });
+  });
+
   test('historySyncNavigatesAwayOnSyncOff', function() {
     navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     assertHistorySyncCardVisible();
 
     // User disables sync while history sync card is shown.
-    setSyncEnabled(false);
+    setupSync({
+      syncOn: false,
+      syncAllDataTypes: false,
+      typedUrlsSynced: false,
+    });
     assertSafeBrowsingCardVisible();
   });
 
   test('historySyncNotReachableWhenSyncOff', function() {
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
-    setSyncEnabled(false);
+    setupSync({
+      syncOn: false,
+      syncAllDataTypes: false,
+      typedUrlsSynced: false,
+    });
     assertSafeBrowsingCardVisible();
   });
 
@@ -409,7 +662,11 @@
       'historySyncCardForwardNavigationShouldShowSafeBrowsingCard',
       async function() {
         navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
-        setSyncEnabled(true);
+        setupSync({
+          syncOn: true,
+          syncAllDataTypes: true,
+          typedUrlsSynced: true,
+        });
         setSafeBrowsingSetting(SafeBrowsingSetting.ENHANCED);
         setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY);
         assertHistorySyncCardVisible();
@@ -430,7 +687,11 @@
   test(
       'historySyncCardForwardNavigationShouldHideSafeBrowsingCard', function() {
         navigateToStep(PrivacyReviewStep.HISTORY_SYNC);
-        setSyncEnabled(true);
+        setupSync({
+          syncOn: true,
+          syncAllDataTypes: true,
+          typedUrlsSynced: true,
+        });
         setSafeBrowsingSetting(SafeBrowsingSetting.DISABLED);
         setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY);
         assertHistorySyncCardVisible();
@@ -441,7 +702,11 @@
 
   test('safeBrowsingCardBackNavigationSyncOn', async function() {
     navigateToStep(PrivacyReviewStep.SAFE_BROWSING);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     assertSafeBrowsingCardVisible();
 
     page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click();
@@ -452,9 +717,49 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickSafeBrowsing');
   });
 
-  test('safeBrowsingCardBackNavigationSyncOff', function() {
+  test('safeBrowsingMetricsEnhancedToEnhanced', async function() {
+    await assertSafeBrowsingMetrics({
+      safeBrowsingStartsEnhanced: true,
+      changeSetting: false,
+      expectedMetric:
+          PrivacyGuideSettingsStates.SAFE_BROWSING_ENHANCED_TO_ENHANCED,
+    });
+  });
+
+  test('safeBrowsingMetricsEnhancedToStandard', async function() {
+    await assertSafeBrowsingMetrics({
+      safeBrowsingStartsEnhanced: true,
+      changeSetting: true,
+      expectedMetric:
+          PrivacyGuideSettingsStates.SAFE_BROWSING_ENHANCED_TO_STANDARD,
+    });
+  });
+
+  test('safeBrowsingMetricsStandardToEnhanced', async function() {
+    await assertSafeBrowsingMetrics({
+      safeBrowsingStartsEnhanced: false,
+      changeSetting: true,
+      expectedMetric:
+          PrivacyGuideSettingsStates.SAFE_BROWSING_STANDARD_TO_ENHANCED,
+    });
+  });
+
+  test('safeBrowsingMetricsStandardToStandard', async function() {
+    await assertSafeBrowsingMetrics({
+      safeBrowsingStartsEnhanced: false,
+      changeSetting: false,
+      expectedMetric:
+          PrivacyGuideSettingsStates.SAFE_BROWSING_STANDARD_TO_STANDARD,
+    });
+  });
+
+  test('safeBrowsingCardBackNavigationSyncOff', async function() {
     navigateToStep(PrivacyReviewStep.SAFE_BROWSING);
-    setSyncEnabled(false);
+    setupSync({
+      syncOn: false,
+      syncAllDataTypes: false,
+      typedUrlsSynced: false,
+    });
     assertSafeBrowsingCardVisible();
 
     page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click();
@@ -519,7 +824,11 @@
 
   test('cookiesCardBackNavigationShouldShowSafeBrowsingCard', async function() {
     navigateToStep(PrivacyReviewStep.COOKIES);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     setSafeBrowsingSetting(SafeBrowsingSetting.STANDARD);
     assertCookiesCardVisible();
 
@@ -532,9 +841,46 @@
     assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickCookies');
   });
 
+  test('cookiesMetrics3PIncognitoTo3PIncognito', async function() {
+    await assertCookieMetrics({
+      cookieStartsBlock3PIncognito: true,
+      changeSetting: false,
+      expectedMetric:
+          PrivacyGuideSettingsStates.BLOCK_3P_INCOGNITO_TO_3P_INCOGNITO,
+    });
+  });
+
+  test('cookiesMetrics3PIncognitoTo3P', async function() {
+    await assertCookieMetrics({
+      cookieStartsBlock3PIncognito: true,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.BLOCK_3P_INCOGNITO_TO_3P,
+    });
+  });
+
+  test('cookiesMetrics3PTo3PIncognito', async function() {
+    await assertCookieMetrics({
+      cookieStartsBlock3PIncognito: false,
+      changeSetting: true,
+      expectedMetric: PrivacyGuideSettingsStates.BLOCK_3P_TO_3P_INCOGNITO,
+    });
+  });
+
+  test('cookiesMetrics3PTo3P', async function() {
+    await assertCookieMetrics({
+      cookieStartsBlock3PIncognito: false,
+      changeSetting: false,
+      expectedMetric: PrivacyGuideSettingsStates.BLOCK_3P_TO_3P,
+    });
+  });
+
   test('cookiesCardBackNavigationShouldHideSafeBrowsingCard', function() {
     navigateToStep(PrivacyReviewStep.COOKIES);
-    setSyncEnabled(true);
+    setupSync({
+      syncOn: true,
+      syncAllDataTypes: true,
+      typedUrlsSynced: true,
+    });
     setSafeBrowsingSetting(SafeBrowsingSetting.DISABLED);
     assertCookiesCardVisible();
 
diff --git a/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts b/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts
index 8a12ee7..59e11313 100644
--- a/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts
+++ b/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {MetricsBrowserProxy, PrivacyElementInteractions, PrivacyGuideInteractions, SafeBrowsingInteractions, SafetyCheckInteractions} from 'chrome://settings/settings.js';
+import {MetricsBrowserProxy, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions} from 'chrome://settings/settings.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 export class TestMetricsBrowserProxy extends TestBrowserProxy implements
@@ -15,6 +15,7 @@
       'recordSafeBrowsingInteractionHistogram',
       'recordPrivacyGuideNextNavigationHistogram',
       'recordPrivacyGuideEntryExitHistogram',
+      'recordPrivacyGuideSettingsStatesHistogram',
     ]);
   }
 
@@ -43,4 +44,8 @@
   recordPrivacyGuideEntryExitHistogram(interaction: PrivacyGuideInteractions) {
     this.methodCalled('recordPrivacyGuideEntryExitHistogram', interaction);
   }
+
+  recordPrivacyGuideSettingsStatesHistogram(state: PrivacyGuideSettingsStates) {
+    this.methodCalled('recordPrivacyGuideSettingsStatesHistogram', state);
+  }
 }
diff --git a/chrome/test/data/webui/signin/BUILD.gn b/chrome/test/data/webui/signin/BUILD.gn
index 6fb3595..15c2863d 100644
--- a/chrome/test/data/webui/signin/BUILD.gn
+++ b/chrome/test/data/webui/signin/BUILD.gn
@@ -15,7 +15,6 @@
   "profile_card_menu_test.ts",
   "profile_picker_app_test.ts",
   "profile_picker_main_view_test.ts",
-  "sync_confirmation_test.ts",
   "test_manage_profiles_browser_proxy.ts",
 ]
 
@@ -28,6 +27,7 @@
   "profile_customization_test.ts",
   "profile_switch_test.ts",
   "profile_type_choice_test.ts",
+  "sync_confirmation_test.ts",
   "test_enterprise_profile_welcome_browser_proxy.ts",
   "test_profile_customization_browser_proxy.ts",
   "test_sync_confirmation_browser_proxy.ts",
diff --git a/chrome/test/data/webui/signin/profile_type_choice_test.ts b/chrome/test/data/webui/signin/profile_type_choice_test.ts
index 50062ce..72e7e91d 100644
--- a/chrome/test/data/webui/signin/profile_type_choice_test.ts
+++ b/chrome/test/data/webui/signin/profile_type_choice_test.ts
@@ -6,9 +6,8 @@
 
 import {ProfileTypeChoiceElement} from 'chrome://profile-picker/lazy_load.js';
 import {ManageProfilesBrowserProxyImpl} from 'chrome://profile-picker/profile_picker.js';
-import {isLacros} from 'chrome://resources/js/cr.m.js';
 
-import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {isChildVisible} from 'chrome://webui-test/test_util.js';
 
 import {TestManageProfilesBrowserProxy} from './test_manage_profiles_browser_proxy.js';
@@ -34,8 +33,7 @@
   });
 
   test('NotNowButton', function() {
-    // Local profile creation is not enabled on Lacros.
-    assertEquals(isChildVisible(choice, '#notNowButton'), !isLacros);
+    assertTrue(isChildVisible(choice, '#notNowButton'));
   });
 
   test('VerifySignInPromoImpressionRecorded', function() {
diff --git a/chrome/test/data/webui/signin/sync_confirmation_test.ts b/chrome/test/data/webui/signin/sync_confirmation_test.ts
index c7861c09..886638a 100644
--- a/chrome/test/data/webui/signin/sync_confirmation_test.ts
+++ b/chrome/test/data/webui/signin/sync_confirmation_test.ts
@@ -8,19 +8,16 @@
 import {SyncConfirmationAppElement} from 'chrome://sync-confirmation/sync_confirmation_app.js';
 import {SyncConfirmationBrowserProxyImpl} from 'chrome://sync-confirmation/sync_confirmation_browser_proxy.js';
 import {assertEquals} from 'chrome://webui-test/chai_assert.js';
-// <if expr="lacros">
 import {assertFalse} from 'chrome://webui-test/chai_assert.js';
-// </if>
-// <if expr="not lacros">
 import {assertTrue} from 'chrome://webui-test/chai_assert.js';
-// </if>
 
 import {TestSyncConfirmationBrowserProxy} from './test_sync_confirmation_browser_proxy.js';
 
 [true, false].forEach(isNewDesignEnabled => {
-  const suiteSuffix = isNewDesignEnabled ? 'NewDesign' : 'OldDesign';
+  const suiteDesignSuffix = isNewDesignEnabled ? 'NewDesign' : 'OldDesign';
 
-  // <if expr="not lacros">
+  // Sync forced comes with different strings but these come from the UI class
+  // so loadTimeData.overrideValues() does not help here.s
   const STANDARD_TITLE = 'Turn on sync?';
   const STANDARD_CONSENT_DESCRIPTION_TEXT = [
     STANDARD_TITLE,
@@ -29,104 +26,105 @@
         'services',
   ];
   const STANDARD_CONSENT_CONFIRMATION = 'Yes, I\'m in';
-  // </if>
-  // <if expr="lacros">
-  const STANDARD_TITLE = 'Chrome browser sync is on';
-  const STANDARD_CONSENT_DESCRIPTION_TEXT = [
-    STANDARD_TITLE,
-    'Your bookmarks, passwords, history, and more are synced on all your ' +
-        'devices',
-    'Google may use your history to personalize Search and other Google ' +
-        'services',
-  ];
-  const STANDARD_CONSENT_CONFIRMATION = 'Done';
-  // </if>
 
-  suite(`SigninSyncConfirmationTest${suiteSuffix}`, function() {
-    let app: SyncConfirmationAppElement;
+  [true, false].forEach(syncForcedEnabled => {
+    const suiteForcedSuffix = syncForcedEnabled ? 'SyncForced' : 'SyncOptional';
 
-    setup(async function() {
-      const browserProxy = new TestSyncConfirmationBrowserProxy();
-      SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
-      loadTimeData.overrideValues({isNewDesign: isNewDesignEnabled});
-      document.body.innerHTML = '';
-      app = document.createElement('sync-confirmation-app');
-      document.body.append(app);
-      // Check that the account image is requested when the app element is
-      // attached to the document.
-      await browserProxy.whenCalled('requestAccountInfo');
-    });
+    suite(
+        `SigninSyncConfirmationTest${suiteDesignSuffix}${suiteForcedSuffix}`,
+        function() {
+          let app: SyncConfirmationAppElement;
 
-    // Tests that no DCHECKS are thrown during initialization of the UI.
-    test('LoadPage', function() {
-      assertEquals(
-          STANDARD_TITLE,
-          app.shadowRoot!.querySelector(
-                             '#syncConfirmationHeading')!.textContent!.trim());
+          setup(async function() {
+            const browserProxy = new TestSyncConfirmationBrowserProxy();
+            SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
+            loadTimeData.overrideValues({
+              isNewDesign: isNewDesignEnabled,
+              syncForced: syncForcedEnabled
+            });
+            document.body.innerHTML = '';
+            app = document.createElement('sync-confirmation-app');
+            document.body.append(app);
+            // Check that the account image is requested when the app element is
+            // attached to the document.
+            await browserProxy.whenCalled('requestAccountInfo');
+          });
 
-      const cancelButton = app.shadowRoot!.querySelector(
-          isNewDesignEnabled ? '#notNowButton' : '#cancelButton');
-      // <if expr="lacros">
-      // Test that the Cancel button is hidden on lacros.
-      assertFalse(!!cancelButton);
-      // </if>
-      // <if expr="not lacros">
-      assertTrue(!!cancelButton);
-      // </if>
-    });
+          // Tests that no DCHECKS are thrown during initialization of the UI.
+          test('LoadPage', function() {
+            assertEquals(
+                STANDARD_TITLE,
+                app.shadowRoot!.querySelector('#syncConfirmationHeading')!
+                    .textContent!.trim());
+
+            const cancelButton =
+                app.shadowRoot!.querySelector(
+                    isNewDesignEnabled ? '#notNowButton' : '#cancelButton') as
+                HTMLElement;
+            if (syncForcedEnabled) {
+              assertTrue(cancelButton!.hidden);
+            } else {
+              assertFalse(cancelButton!.hidden);
+            }
+          });
+        });
   });
 
   // This test suite verifies that the consent strings recorded in various
   // scenarios are as expected. If the corresponding HTML file was updated
   // without also updating the attributes referring to consent strings,
   // this test will break.
-  suite(`SigninSyncConfirmationConsentRecordingTest${suiteSuffix}`, function() {
-    let app: SyncConfirmationAppElement;
-    let browserProxy: TestSyncConfirmationBrowserProxy;
+  suite(
+      `SigninSyncConfirmationConsentRecordingTest${suiteDesignSuffix}`,
+      function() {
+        let app: SyncConfirmationAppElement;
+        let browserProxy: TestSyncConfirmationBrowserProxy;
 
-    setup(async function() {
-      // This test suite makes comparisons with strings in their default locale,
-      // which is en-US.
-      assertEquals(
-          'en-US', navigator.language,
-          'Cannot verify strings for the ' + navigator.language + 'locale.');
+        setup(async function() {
+          // This test suite makes comparisons with strings in their default
+          // locale, which is en-US.
+          assertEquals(
+              'en-US', navigator.language,
+              'Cannot verify strings for the ' + navigator.language +
+                  'locale.');
 
-      browserProxy = new TestSyncConfirmationBrowserProxy();
-      SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
-      loadTimeData.overrideValues({isNewDesign: isNewDesignEnabled});
+          browserProxy = new TestSyncConfirmationBrowserProxy();
+          SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
+          loadTimeData.overrideValues({isNewDesign: isNewDesignEnabled});
 
-      document.body.innerHTML = '';
-      app = document.createElement('sync-confirmation-app');
-      document.body.append(app);
-      // Wait for the app element to get attached to the document (which is when
-      // the account image gets requested).
-      await browserProxy.whenCalled('requestAccountInfo');
-    });
+          document.body.innerHTML = '';
+          app = document.createElement('sync-confirmation-app');
+          document.body.append(app);
+          // Wait for the app element to get attached to the document (which is
+          // when the account image gets requested).
+          await browserProxy.whenCalled('requestAccountInfo');
+        });
 
-    // Tests that the expected strings are recorded when clicking the Confirm
-    // button.
-    test('recordConsentOnConfirm', async function() {
-      app.shadowRoot!.querySelector<HTMLElement>('#confirmButton')!.click();
-      const [description, confirmation] =
-          await browserProxy.whenCalled('confirm');
-      assertEquals(
-          JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
-          JSON.stringify(description));
-      assertEquals(STANDARD_CONSENT_CONFIRMATION, confirmation);
-    });
+        // Tests that the expected strings are recorded when clicking the
+        // Confirm button.
+        test('recordConsentOnConfirm', async function() {
+          app.shadowRoot!.querySelector<HTMLElement>('#confirmButton')!.click();
+          const [description, confirmation] =
+              await browserProxy.whenCalled('confirm');
+          assertEquals(
+              JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
+              JSON.stringify(description));
+          assertEquals(STANDARD_CONSENT_CONFIRMATION, confirmation);
+        });
 
-    // Tests that the expected strings are recorded when clicking the Confirm
-    // button.
-    test('recordConsentOnSettingsLink', async function() {
-      app.shadowRoot!.querySelector<HTMLElement>('#settingsButton')!.click();
-      const [description, confirmation] =
-          await browserProxy.whenCalled('goToSettings');
-      assertEquals(
-          JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
-          JSON.stringify(description));
-      // 'Sync settings' is recorded for new design but this is passed from the
-      // UI class so overriding loadTimeData does not help here.
-      assertEquals('Settings', confirmation);
-    });
-  });
+        // Tests that the expected strings are recorded when clicking the
+        // Confirm button.
+        test('recordConsentOnSettingsLink', async function() {
+          app.shadowRoot!.querySelector<HTMLElement>(
+                             '#settingsButton')!.click();
+          const [description, confirmation] =
+              await browserProxy.whenCalled('goToSettings');
+          assertEquals(
+              JSON.stringify(STANDARD_CONSENT_DESCRIPTION_TEXT),
+              JSON.stringify(description));
+          // 'Sync settings' is recorded for new design but this is passed from
+          // the UI class so overriding loadTimeData does not help here.
+          assertEquals('Settings', confirmation);
+        });
+      });
 });
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index e47711f..820e337 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14488.0.0
\ No newline at end of file
+14490.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 195b73d6..02397b336 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2289,8 +2289,8 @@
         Done
       </message>
       <!-- Manual write protect disable complete page -->
-      <message name="IDS_SHIMLESS_RMA_WP_DISABLE_COMPLETE_PAGE_TITLE" translateable="false" desc="Title for the manual write protect disable complete page. Displays next steps, either reassemble device or leave wp disabled until further notice.">
-        Manual write-protect disable complete
+      <message name="IDS_SHIMLESS_RMA_WP_DISABLE_COMPLETE_PAGE_TITLE" translateable="false" desc="Title for the write protect disable complete page. Displays next steps, either reassemble device or leave wp disabled until further notice.">
+        Write Protect is turned off
       </message>
       <message name="IDS_SHIMLESS_RMA_WP_DISABLE_SKIPPED_MESSAGE" translateable="false" desc="If the device already had write protection disabled before reaching the 'choose method' page the flow skips straight to this page and informs the user they can manually re-enable if it is currently manually disabled. It is not possible for the device to determine this automatically, so the instructions must cover both cases.">
         Write protection is already disabled. If the device is disassembled you may reassemble it now.
diff --git a/chromeos/components/onc/onc_signature.cc b/chromeos/components/onc/onc_signature.cc
index 7b06367..e0a8e2740 100644
--- a/chromeos/components/onc/onc_signature.cc
+++ b/chromeos/components/onc/onc_signature.cc
@@ -85,7 +85,9 @@
     {::onc::client_cert::kClientCertType, &kStringSignature},
     {::onc::ipsec::kGroup, &kStringSignature},
     {::onc::ipsec::kIKEVersion, &kIntegerSignature},
+    {::onc::ipsec::kLocalIdentity, &kStringSignature},
     {::onc::ipsec::kPSK, &kStringSignature},
+    {::onc::ipsec::kRemoteIdentity, &kStringSignature},
     {::onc::vpn::kSaveCredentials, &kBoolSignature},
     // Used internally. Not officially supported.
     {::onc::ipsec::kServerCAPEMs, &kStringListSignature},
diff --git a/chromeos/components/test/data/onc/ikev2_psk.onc b/chromeos/components/test/data/onc/ikev2_psk.onc
new file mode 100644
index 0000000..8b637a80
--- /dev/null
+++ b/chromeos/components/test/data/onc/ikev2_psk.onc
@@ -0,0 +1,16 @@
+{ "GUID": "guid",
+  "Type": "VPN",
+  "Name": "MyIKEv2VPN",
+  "VPN": {
+    "Type": "IPsec",
+    "Host": "some.host.org",
+    "IPsec": {
+      "AuthenticationType": "PSK",
+      "IKEVersion": 2,
+      "LocalIdentity": "local-id",
+      "PSK": "some_preshared_key",
+      "RemoteIdentity": "remote-id",
+      "SaveCredentials": true,
+    },
+  }
+}
diff --git a/chromeos/components/test/data/onc/shill_ikev2_psk.json b/chromeos/components/test/data/onc/shill_ikev2_psk.json
new file mode 100644
index 0000000..e81bd12
--- /dev/null
+++ b/chromeos/components/test/data/onc/shill_ikev2_psk.json
@@ -0,0 +1,11 @@
+{ "GUID": "guid",
+  "Type": "vpn",
+  "Name": "MyIKEv2VPN",
+  "Provider.Host": "some.host.org",
+  "Provider.Type": "ikev2",
+  "IKEv2.AuthenticationType": "PSK",
+  "IKEv2.LocalIdentity": "local-id",
+  "IKEv2.PSK": "some_preshared_key",
+  "IKEv2.RemoteIdentity": "remote-id",
+  "SaveCredentials": true
+}
diff --git a/chromeos/components/test/data/onc/shill_output_ikev2_psk.json b/chromeos/components/test/data/onc/shill_output_ikev2_psk.json
new file mode 100644
index 0000000..b1c489f
--- /dev/null
+++ b/chromeos/components/test/data/onc/shill_output_ikev2_psk.json
@@ -0,0 +1,13 @@
+{ "GUID": "guid",
+  "Type": "vpn",
+  "Name": "MyIKEv2VPN",
+  "Provider": {
+    "Host": "some.host.org",
+    "IKEv2.AuthenticationType": "PSK",
+    "IKEv2.LocalIdentity": "local-id",
+    "IKEv2.PSK": "some_preshared_key",
+    "IKEv2.RemoteIdentity": "remote-id",
+    "Type": "ikev2"
+  },
+  "SaveCredentials": true
+}
diff --git a/chromeos/components/test/data/onc/translation_of_shill_ikev2_psk.onc b/chromeos/components/test/data/onc/translation_of_shill_ikev2_psk.onc
new file mode 100644
index 0000000..7b897a4b
--- /dev/null
+++ b/chromeos/components/test/data/onc/translation_of_shill_ikev2_psk.onc
@@ -0,0 +1,22 @@
+{ "GUID": "guid",
+  "Type": "VPN",
+  "Name": "MyIKEv2VPN",
+  "IPAddressConfigType":"DHCP",
+  "NameServersConfigType":"DHCP",
+  "VPN": {
+    "Type": "IPsec",
+    "Host": "some.host.org",
+    "IPsec": {
+      "AuthenticationType": "PSK",
+      // This field is part of ONC (and is required). However, it does not
+      // exist explicitly in the Shill dictionary. As there is no use-case yet
+      // that requires reconstructing this field from a Shill dictionary, we
+      // don't translate it.
+      // "IKEVersion": 2,
+      "LocalIdentity": "local-id",
+      "PSK": "some_preshared_key",
+      "SaveCredentials": true,
+      "RemoteIdentity": "remote-id",
+    },
+  }
+}
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index d07345dc..7ad83091 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -57,6 +57,7 @@
     "screen_manager.mojom",
     "select_file.mojom",
     "structured_metrics_service.mojom",
+    "sync.mojom",
     "system_display.mojom",
     "task_manager.mojom",
     "test_controller.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index a0e139a..010751ab 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -585,6 +585,10 @@
   // The URLs should be set with BrowserInitParams::startup_urls.
   // Added in M96.
   [MinVersion=3] kOpenWindowWithUrls = 5,
+
+  // Opens a new Guest mode window.
+  // Added in M100.
+  [MinVersion=4] kOpenGuestWindow = 6,
 };
 
 // Whether / how mlservice on-device handwriting is supported.
@@ -895,8 +899,8 @@
 // has accidentally become a kitchen sink for different features. This was not
 // intentional.
 //
-// Next MinVersion: 63.
-// Next ID: 14
+// Next MinVersion: 64.
+// Next ID: 15
 //
 [Stable, Uuid="4e04dc16-b34c-40fd-9e3f-3c55c2c6cf91",
  RenamedFrom="crosapi.mojom.LacrosChromeService"]
@@ -933,6 +937,12 @@
       mojo_base.mojom.String16 tab_id, mojo_base.mojom.String16 group_id)
           => (CreationResult result, string app_id);
 
+  // Opens a new window in the browser with the Guest profile if the Guest mode
+  // is enabled.
+  // Added in M100.
+  [MinVersion=63]
+  NewGuestWindow@14() => ();
+
   // Opens a new tab in the browser with, currently, the last used profile.
   // This may open a new window, if there's no window. Please see also
   // the Chrome's NewTab command for details.
diff --git a/chromeos/crosapi/mojom/sync.mojom b/chromeos/crosapi/mojom/sync.mojom
new file mode 100644
index 0000000..9d73640
--- /dev/null
+++ b/chromeos/crosapi/mojom/sync.mojom
@@ -0,0 +1,59 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module crosapi.mojom;
+
+import "chromeos/crosapi/mojom/account_manager.mojom";
+
+// A mojo representation of syncer::Nigori. Should only be obtained by using
+// Nigori::ExportKeys() or direct mapping from other Nigori representations,
+// such as sync_pb::NigoriKey.
+[Stable]
+struct NigoriKey {
+  array<uint8> encryption_key@0;
+  array<uint8> mac_key@1;
+};
+
+// Allows lacros-chrome to observe the explicit-passphrase related state.
+// Next version: 1
+// Next ordinal value: 2
+[Stable, Uuid="aeec552c-67c7-43dc-bbcf-d2fcc7c6a754"]
+interface SyncExplicitPassphraseClientObserver {
+  // Called when passphrase became required for observed client (e.g. explicit
+  // passphrase Nigori update is received and correct passphrase is not yet
+  // available).
+  OnPassphraseRequired@0();
+
+  // Called when passphrase became available for observed client (e.g. user
+  // entered the correct passphrase or passphrase obtained by other way, such
+  // as SetDecryptionNigoriKey() IPC below).
+  OnPassphraseAvailable@1();
+};
+
+// Defines a Sync API related to explicit passphrase sharing that lives in
+// ash-chrome and is accessed from lacros-chrome.
+// Next version: 1
+// Next ordinal value: 3
+[Stable, Uuid="4d13845c-a628-404b-8a88-c39a0aeea298"]
+interface SyncExplicitPassphraseClient {
+  // Adds a new observer.
+  AddObserver@0(pending_remote<SyncExplicitPassphraseClientObserver> observer);
+
+  // Attempts to retrieve explicit passphrase key. |account_key| is used to
+  // verify that the decryption key is requested for the primary profile syncing
+  // account. Returns null if no key is available.
+  GetDecryptionNigoriKey@1(AccountKey account_key) =>
+    (NigoriKey? decryption_key);
+
+  // Attempts to set explicit passphrase decryption key. It's safe to call this
+  // method when passphrase is not required or with non-matching (outdated key
+  // or key that is not yet needed for ash-chrome SyncService), because
+  // SyncService will verify |decryption_key| against sync data. However,
+  // |decryption_key| must belong to the account specified by |account_key| and
+  // must be obtained by the user input or from Ash. |account_key| is used to
+  // verify that the decryption key is passed for the primary profile syncing
+  // account.
+  SetDecryptionNigoriKey@2(AccountKey account_key,
+                           NigoriKey decryption_key);
+};
diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc
index 191f82f..59e06b6 100644
--- a/chromeos/network/onc/onc_translation_tables.cc
+++ b/chromeos/network/onc/onc_translation_tables.cc
@@ -43,6 +43,7 @@
      shill::kEapUseProactiveKeyCachingProperty},
     {nullptr}};
 
+// This group of fields are for L2TP/IPsec, see |kIPsecIKEv2Table| for IKEv2.
 const FieldTranslationEntry ipsec_fields[] = {
     // This field is converted during translation, see onc_translator_*.
     // { ::onc::ipsec::kAuthenticationType, shill::kL2tpIpsecAuthenticationType
@@ -343,6 +344,7 @@
     {nullptr}};
 
 const StringTranslationEntry kVPNTypeTable[] = {
+    {::onc::vpn::kIPsec, shill::kProviderIKEv2},
     {::onc::vpn::kTypeL2TP_IPsec, shill::kProviderL2tpIpsec},
     {::onc::vpn::kOpenVPN, shill::kProviderOpenVpn},
     {::onc::vpn::kWireGuard, shill::kProviderWireGuard},
@@ -418,6 +420,12 @@
     {::onc::openvpn_compression_algorithm::kLzo, shill::kOpenVPNCompressLzo},
     {nullptr}};
 
+const StringTranslationEntry kIKEv2AuthenticationTypeTable[] = {
+    {::onc::ipsec::kPSK, shill::kIKEv2AuthenticationTypePSK},
+    {::onc::ipsec::kCert, shill::kIKEv2AuthenticationTypeCert},
+    {::onc::ipsec::kEAP, shill::kIKEv2AuthenticationTypeEAP},
+    {nullptr}};
+
 // This must contain only Shill Device properties and no Service properties.
 // For Service properties see cellular_fields.
 const FieldTranslationEntry kCellularDeviceTable[] = {
@@ -444,6 +452,13 @@
     {::onc::cellular::kSupportNetworkScan, shill::kSupportNetworkScanProperty},
     {nullptr}};
 
+const FieldTranslationEntry kIPsecIKEv2Table[] = {
+    {::onc::ipsec::kPSK, shill::kIKEv2PskProperty},
+    {::onc::ipsec::kServerCAPEMs, shill::kIKEv2CaCertPemProperty},
+    {::onc::ipsec::kLocalIdentity, shill::kIKEv2LocalIdentityProperty},
+    {::onc::ipsec::kRemoteIdentity, shill::kIKEv2RemoteIdentityProperty},
+    {nullptr}};
+
 const FieldTranslationEntry* GetFieldTranslationTable(
     const OncValueSignature& onc_signature) {
   for (const OncValueTranslationEntry* it = onc_value_translation_table;
diff --git a/chromeos/network/onc/onc_translation_tables.h b/chromeos/network/onc/onc_translation_tables.h
index a0a48190..dc91d8a 100644
--- a/chromeos/network/onc/onc_translation_tables.h
+++ b/chromeos/network/onc/onc_translation_tables.h
@@ -46,12 +46,20 @@
 extern const StringTranslationEntry kRoamingStateTable[];
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const StringTranslationEntry kOpenVpnCompressionAlgorithmTable[];
+COMPONENT_EXPORT(CHROMEOS_NETWORK)
+extern const StringTranslationEntry kIKEv2AuthenticationTypeTable[];
 
 // A separate translation table for cellular properties that are stored in a
 // Shill Device instead of a Service. The |shill_property_name| entries
 // reference Device properties, not Service properties.
 extern const FieldTranslationEntry kCellularDeviceTable[];
 
+// A separate translation table for IPsec properties that need to be mapped to
+// an IKEv2 VPN service, while the default one for IPsec (|ipsec_fields| defined
+// in the .cc file) is for the L2TP/IPsec VPN services. Only used in the
+// shill-to-onc translation but not the opposite direction.
+extern const FieldTranslationEntry kIPsecIKEv2Table[];
+
 const FieldTranslationEntry* GetFieldTranslationTable(
     const OncValueSignature& onc_signature);
 
diff --git a/chromeos/network/onc/onc_translator_onc_to_shill.cc b/chromeos/network/onc/onc_translator_onc_to_shill.cc
index 78ea0dc0..ecd6b64 100644
--- a/chromeos/network/onc/onc_translator_onc_to_shill.cc
+++ b/chromeos/network/onc/onc_translator_onc_to_shill.cc
@@ -246,15 +246,30 @@
 }
 
 void LocalTranslator::TranslateIPsec() {
-  SetClientCertProperties(client_cert::CONFIG_TYPE_IPSEC, onc_object_,
-                          shill_dictionary_);
+  const auto ike_version = onc_object_->FindIntKey(::onc::ipsec::kIKEVersion);
+  if (ike_version.has_value() && ike_version.value() == 2) {
+    // The translation table set in this object is for L2TP/IPsec, so we do the
+    // copy manually.
+    CopyFieldFromONCToShill(::onc::ipsec::kAuthenticationType,
+                            shill::kIKEv2AuthenticationTypeProperty);
+    CopyFieldFromONCToShill(::onc::ipsec::kPSK, shill::kIKEv2PskProperty);
+    CopyFieldFromONCToShill(::onc::ipsec::kServerCAPEMs,
+                            shill::kIKEv2CaCertPemProperty);
+    CopyFieldFromONCToShill(::onc::ipsec::kLocalIdentity,
+                            shill::kIKEv2LocalIdentityProperty);
+    CopyFieldFromONCToShill(::onc::ipsec::kRemoteIdentity,
+                            shill::kIKEv2RemoteIdentityProperty);
+  } else {
+    // For L2TP/IPsec.
+    SetClientCertProperties(client_cert::CONFIG_TYPE_IPSEC, onc_object_,
+                            shill_dictionary_);
+    CopyFieldsAccordingToSignature();
+  }
 
   // SaveCredentials needs special handling when translating from Shill -> ONC
   // so handle it explicitly here.
   CopyFieldFromONCToShill(::onc::vpn::kSaveCredentials,
                           shill::kSaveCredentialsProperty);
-
-  CopyFieldsAccordingToSignature();
 }
 
 void LocalTranslator::TranslateL2TP() {
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc
index f933ea9..5afc6a8 100644
--- a/chromeos/network/onc/onc_translator_shill_to_onc.cc
+++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -135,6 +135,14 @@
   void TranslateEap();
 
   // Creates an ONC object from |dictionary| according to the signature
+  // associated to |onc_field_name| and |field_translation_table|, and adds it
+  // to |onc_object_| at |onc_field_name|.
+  void TranslateAndAddNestedObject(
+      const std::string& onc_field_name,
+      const base::Value& dictionary,
+      const FieldTranslationEntry* field_translation_table);
+
+  // Creates an ONC object from |dictionary| according to the signature
   // associated to |onc_field_name| and adds it to |onc_object_| at
   // |onc_field_name|.
   void TranslateAndAddNestedObject(const std::string& onc_field_name,
@@ -317,6 +325,16 @@
 
 void ShillToONCTranslator::TranslateIPsec() {
   CopyPropertiesAccordingToSignature();
+
+  if (field_translation_table_ == kIPsecIKEv2Table) {
+    // This is an IKEv2 VPN service.
+    TranslateWithTableAndSet(shill::kIKEv2AuthenticationTypeProperty,
+                             kIKEv2AuthenticationTypeTable,
+                             ::onc::ipsec::kAuthenticationType);
+    return;
+  }
+
+  // This is an L2TP/IPsec VPN service.
   if (shill_dictionary_->FindKey(shill::kL2tpIpsecXauthUserProperty))
     TranslateAndAddNestedObject(::onc::ipsec::kXAUTH);
 
@@ -387,6 +405,10 @@
     TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider);
     TranslateAndAddNestedObject(::onc::vpn::kL2TP, *provider);
     provider_type_dictionary = ::onc::vpn::kIPsec;
+  } else if (shill_provider_type == shill::kProviderIKEv2) {
+    TranslateAndAddNestedObject(::onc::vpn::kIPsec, *provider,
+                                kIPsecIKEv2Table);
+    provider_type_dictionary = ::onc::vpn::kIPsec;
   } else {
     TranslateAndAddNestedObject(onc_provider_type, *provider);
     provider_type_dictionary = onc_provider_type;
@@ -784,9 +806,24 @@
     NET_LOG(ERROR) << "Unable to find signature for field: " << onc_field_name;
     return;
   }
-  ShillToONCTranslator nested_translator(dictionary, onc_source_,
-                                         *field_signature->value_signature,
-                                         network_state_);
+  TranslateAndAddNestedObject(
+      onc_field_name, dictionary,
+      GetFieldTranslationTable(*field_signature->value_signature));
+}
+
+void ShillToONCTranslator::TranslateAndAddNestedObject(
+    const std::string& onc_field_name,
+    const base::Value& dictionary,
+    const FieldTranslationEntry* field_translation_table) {
+  const OncFieldSignature* field_signature =
+      GetFieldSignature(*onc_signature_, onc_field_name);
+  if (!field_signature) {
+    NET_LOG(ERROR) << "Unable to find signature for field: " << onc_field_name;
+    return;
+  }
+  ShillToONCTranslator nested_translator(
+      dictionary, onc_source_, *field_signature->value_signature,
+      field_translation_table, network_state_);
   base::Value nested_object = nested_translator.CreateTranslatedONCObject();
   if (nested_object.DictEmpty())
     return;
diff --git a/chromeos/network/onc/onc_translator_unittest.cc b/chromeos/network/onc/onc_translator_unittest.cc
index bf0c8ced..9d98a0b 100644
--- a/chromeos/network/onc/onc_translator_unittest.cc
+++ b/chromeos/network/onc/onc_translator_unittest.cc
@@ -57,6 +57,7 @@
         std::make_pair("wifi_eap_ttls.onc", "shill_wifi_eap_ttls.json"),
         std::make_pair("wifi_proxy.onc", "shill_wifi_proxy.json"),
         std::make_pair("wifi_proxy_pac.onc", "shill_wifi_proxy_pac.json"),
+        std::make_pair("ikev2_psk.onc", "shill_ikev2_psk.json"),
         std::make_pair("l2tpipsec_clientcert_with_cert_pems.onc",
                        "shill_l2tpipsec_clientcert.json"),
         std::make_pair("valid_openvpn_with_cert_pems.onc",
@@ -123,6 +124,8 @@
                        "translation_of_shill_wifi_non_utf8_ssid.onc"),
         std::make_pair("shill_wifi_wep_8021x_clientcert.json",
                        "translation_of_shill_wifi_wep_8021x_clientcert.onc"),
+        std::make_pair("shill_output_ikev2_psk.json",
+                       "translation_of_shill_ikev2_psk.onc"),
         std::make_pair("shill_output_l2tpipsec.json",
                        "translation_of_shill_l2tpipsec.onc"),
         std::make_pair("shill_output_wireguard.json",
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index dfc90db..7266f6c 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-99-4827.0-1643629123-benchmark-99.0.4844.16-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-99-4827.0-1643629123-benchmark-99.0.4844.17-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index d948d8fd..82a0d3e 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-99-4827.0-1643628001-benchmark-99.0.4844.16-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-99-4827.0-1643628001-benchmark-99.0.4844.17-r1-redacted.afdo.xz
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index d90733c..212c0d5 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -97,6 +97,9 @@
   # https://crbug.com/1279285: Flaky.
   "policy.AllowWakeLocks",
 
+  # https://crbug.com/1285206
+  "policy.DeveloperToolsAvailability",
+
   # https://crbug.com/1281645
   "quicksettings.LockScreen",
 
diff --git a/components/autofill/content/common/mojom/autofill_agent.mojom b/components/autofill/content/common/mojom/autofill_agent.mojom
index 0a4e5ce..6a0aef4 100644
--- a/components/autofill/content/common/mojom/autofill_agent.mojom
+++ b/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -117,6 +117,10 @@
   // Indicates whether the virtual keyboard should be shown instead.
   TouchToFillClosed(bool show_virtual_keyboard);
 
+  // Triggers a form submission on the last interacted element.
+  [EnableIf=is_android]
+  TriggerFormSubmission();
+
   // Annotate password related (username, password) DOM input elements with
   // corresponding HTML attributes. It is used only for debugging.
   AnnotateFieldsWithParsingResult(ParsingResult parsing_result);
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index ed06cd78..1110c8a 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -779,9 +779,6 @@
   mutable_filled_element.SetSelectionRange(element->Value().length(),
                                            element->Value().length());
 
-  // TODO(crbug.com/1283004): Submit the form if filling is caused by
-  // TouchToFill.
-
   return true;
 }
 
@@ -1476,6 +1473,33 @@
   field_data_manager_->ClearData();
 }
 
+#if BUILDFLAG(IS_ANDROID)
+void PasswordAutofillAgent::TriggerFormSubmission() {
+  // Find the last interacted element to simulate an enter keystroke at.
+  WebFormControlElement form_control = FindFormControlElementByUniqueRendererId(
+      render_frame()->GetWebFrame()->GetDocument(),
+      last_updated_field_renderer_id_, last_updated_form_renderer_id_);
+  if (form_control.IsNull()) {
+    // The target field doesn't exist anymore. Don't try to submit it.
+    return;
+  }
+
+  // TODO(crbug.com/1283004): Support submission for <form>less forms too.
+  if (!form_control.Form().IsNull()) {
+    WebInputElement* input = ToWebInputElement(&form_control);
+    // |form_control| can only be |WebInputElement|, not |WebSelectElement|.
+    DCHECK(!input || !input->IsNull())
+        << "Form submission attempt for a non-input element";
+
+    // TODO(crbug.com/1283004): Support filling single username fields too.
+    DCHECK(input->IsPasswordFieldForAutofill())
+        << "Form submission attempt for a non-password element";
+
+    input->DispatchSimulatedEnterIfLastInputInForm();
+  }
+}
+#endif
+
 void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
   DCHECK(!node.IsNull());
   focused_input_element_.Reset();
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 4bc2dc7..c89e17a 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -139,6 +139,9 @@
   void TouchToFillClosed(bool show_virtual_keyboard) override;
   void AnnotateFieldsWithParsingResult(
       const ParsingResult& parsing_result) override;
+#if BUILDFLAG(IS_ANDROID)
+  void TriggerFormSubmission() override;
+#endif
 
   // FormTracker::Observer
   void OnProvisionallySaveForm(const blink::WebFormElement& form,
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn
index 77b5ffc..201801ac 100644
--- a/components/browser_ui/styles/android/BUILD.gn
+++ b/components/browser_ui/styles/android/BUILD.gn
@@ -159,6 +159,8 @@
     "java/res/drawable-xxxhdpi/top_round_shadow.9.png",
     "java/res/drawable/checkmark_blue.xml",
     "java/res/drawable/circle_white.xml",
+    "java/res/drawable/gm_ads_click_24.xml",
+    "java/res/drawable/gm_insert_chart_24.xml",
     "java/res/drawable/ic_account_circle_24dp.xml",
     "java/res/drawable/ic_add.xml",
     "java/res/drawable/ic_bar_chart_24dp.xml",
@@ -193,6 +195,7 @@
     "java/res/drawable/ic_remove.xml",
     "java/res/drawable/ic_security_grey.xml",
     "java/res/drawable/ic_settings_black.xml",
+    "java/res/drawable/ic_spam_reduction_24dp.xml",
     "java/res/drawable/ic_tune_24dp.xml",
     "java/res/drawable/ic_update_grey.xml",
     "java/res/drawable/ic_videocam_24dp.xml",
diff --git a/components/browser_ui/styles/android/java/res/drawable/gm_ads_click_24.xml b/components/browser_ui/styles/android/java/res/drawable/gm_ads_click_24.xml
new file mode 100644
index 0000000..206a084
--- /dev/null
+++ b/components/browser_ui/styles/android/java/res/drawable/gm_ads_click_24.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2022 The Chromium Authors. All rights reserved.
+     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:fillColor="@android:color/white"
+      android:pathData="M11.71,17.99C8.53,17.84 6,15.22 6,12c0,-3.31 2.69,-6 6,-6c3.22,0 5.84,2.53 5.99,5.71l-2.1,-0.63C15.48,9.31 13.89,8 12,8c-2.21,0 -4,1.79 -4,4c0,1.89 1.31,3.48 3.08,3.89L11.71,17.99zM22,12c0,0.3 -0.01,0.6 -0.04,0.9l-1.97,-0.59C20,12.21 20,12.1 20,12c0,-4.42 -3.58,-8 -8,-8s-8,3.58 -8,8s3.58,8 8,8c0.1,0 0.21,0 0.31,-0.01l0.59,1.97C12.6,21.99 12.3,22 12,22C6.48,22 2,17.52 2,12C2,6.48 6.48,2 12,2S22,6.48 22,12zM18.23,16.26L22,15l-10,-3l3,10l1.26,-3.77l4.27,4.27l1.98,-1.98L18.23,16.26z"/>
+</vector>
diff --git a/components/browser_ui/styles/android/java/res/drawable/gm_insert_chart_24.xml b/components/browser_ui/styles/android/java/res/drawable/gm_insert_chart_24.xml
new file mode 100644
index 0000000..1b950b3
--- /dev/null
+++ b/components/browser_ui/styles/android/java/res/drawable/gm_insert_chart_24.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2022 The Chromium Authors. All rights reserved.
+     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:fillColor="@android:color/white"
+      android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,5h14v14zM7,10h2v7L7,17zM11,7h2v10h-2zM15,13h2v4h-2z"/>
+</vector>
diff --git a/components/browser_ui/styles/android/java/res/drawable/ic_spam_reduction_24dp.xml b/components/browser_ui/styles/android/java/res/drawable/ic_spam_reduction_24dp.xml
new file mode 100644
index 0000000..afcf4710
--- /dev/null
+++ b/components/browser_ui/styles/android/java/res/drawable/ic_spam_reduction_24dp.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2022 The Chromium Authors. All rights reserved.
+     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:fillColor="@android:color/white"
+      android:pathData="M18.09,8L18.09,4.2h1.71v4.67h-1.71L18.09,8ZM18.09,11.8h1.71v-1.73h-1.71v1.73ZM11.66,13.13c2.29,0 6.85,1.16 6.85,3.47v2.6L4.8,19.2v-2.6c0,-2.3 4.57,-3.47 6.86,-3.47ZM11.66,5.33c0.9,0 1.78,0.37 2.42,1.02a3.49,3.49 0,0 1,-2.42 5.92c-0.91,0 -1.78,-0.37 -2.43,-1.02a3.49,3.49 0,0 1,2.43 -5.92ZM11.66,14.78c-2.55,0 -5.23,1.27 -5.23,1.82v0.95h10.46v-0.95c0,-0.55 -2.69,-1.82 -5.23,-1.82ZM11.66,6.98c-0.48,0 -0.94,0.2 -1.28,0.53a1.83,1.83 0,0 0,1.28 3.11c0.47,0 0.93,-0.2 1.27,-0.53a1.83,1.83 0,0 0,-1.27 -3.11Z"/>
+</vector>
diff --git a/components/onc/docs/onc_spec.md b/components/onc/docs/onc_spec.md
index 3eb379e..b567ad0 100644
--- a/components/onc/docs/onc_spec.md
+++ b/components/onc/docs/onc_spec.md
@@ -592,6 +592,7 @@
     * (required) - **string**
     * Allowed values are:
         * *ARCVPN*
+        * *IPsec*
         * *L2TP-IPsec*
         * *OpenVPN*
         * *ThirdPartyVPN*
@@ -655,6 +656,10 @@
     * (required) - **integer**
     * Version of IKE protocol to use.
 
+* **LocalIdentity**
+    * (optional if **IKEVersion** is 2, otherwise ignored) - **string**
+    * The local identity used in IKE authentication.
+
 * **PSK**
     * (optional if **AuthenticationType** is *PSK*, otherwise ignored)
       - **string**
@@ -662,6 +667,10 @@
       If the value is saved but not known, this may be set to an empty value,
       indicating that the UI does not need to provide it.
 
+* **RemoteIdentity**
+    * (optional if **IKEVersion** is 2, otherwise ignored) - **string**
+    * The remote identity used in IKE authentication.
+
 * **SaveCredentials**
     * (optional if **AuthenticationType**
           is *PSK*, otherwise ignored, defaults to *false*) - **boolean**
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc
index 5e6cd9ee..04e50f0 100644
--- a/components/onc/onc_constants.cc
+++ b/components/onc/onc_constants.cc
@@ -366,7 +366,9 @@
 const char kEAP[] = "EAP";
 const char kGroup[] = "Group";
 const char kIKEVersion[] = "IKEVersion";
+const char kLocalIdentity[] = "LocalIdentity";
 const char kPSK[] = "PSK";
+const char kRemoteIdentity[] = "RemoteIdentity";
 const char kServerCAPEMs[] = "ServerCAPEMs";
 const char kServerCARef[] = "ServerCARef";
 const char kServerCARefs[] = "ServerCARefs";
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h
index 6a6a221..d60c916 100644
--- a/components/onc/onc_constants.h
+++ b/components/onc/onc_constants.h
@@ -382,7 +382,9 @@
 COMPONENT_EXPORT(ONC) extern const char kEAP[];
 COMPONENT_EXPORT(ONC) extern const char kGroup[];
 COMPONENT_EXPORT(ONC) extern const char kIKEVersion[];
+COMPONENT_EXPORT(ONC) extern const char kLocalIdentity[];
 COMPONENT_EXPORT(ONC) extern const char kPSK[];
+COMPONENT_EXPORT(ONC) extern const char kRemoteIdentity[];
 COMPONENT_EXPORT(ONC) extern const char kServerCAPEMs[];
 COMPONENT_EXPORT(ONC) extern const char kServerCARef[];
 COMPONENT_EXPORT(ONC) extern const char kServerCARefs[];
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationController.java
index fd4b6747..33650d1 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationController.java
@@ -34,7 +34,7 @@
         PageInfoRowView.ViewParams rowParams = new PageInfoRowView.ViewParams();
         rowParams.visible = !mInfo.isEmpty();
         rowParams.title = getSubpageTitle();
-        rowParams.iconResId = R.drawable.permission_cookie;
+        rowParams.iconResId = R.drawable.gm_ads_click_24;
         rowParams.decreaseIconSize = true;
         rowParams.clickCallback = this::launchSubpage;
         mRowView.setParams(rowParams);
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc
index fd2331e9..182d2eb 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -177,6 +177,12 @@
   GetPasswordAutofillAgent()->FillIntoFocusedField(is_password, credential);
 }
 
+#if BUILDFLAG(IS_ANDROID)
+void ContentPasswordManagerDriver::TriggerFormSubmission() {
+  GetPasswordAutofillAgent()->TriggerFormSubmission();
+}
+#endif
+
 void ContentPasswordManagerDriver::PreviewSuggestion(
     const std::u16string& username,
     const std::u16string& password) {
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h
index 01885641..0a432ea 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -73,6 +73,9 @@
                       const std::u16string& password) override;
   void FillIntoFocusedField(bool is_password,
                             const std::u16string& credential) override;
+#if BUILDFLAG(IS_ANDROID)
+  void TriggerFormSubmission() override;
+#endif
   void PreviewSuggestion(const std::u16string& username,
                          const std::u16string& password) override;
   void ClearPreviewedForm() override;
diff --git a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
index e47067f..136b3a7e 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
@@ -92,6 +92,9 @@
               (bool, const std::u16string&),
               (override));
   MOCK_METHOD(void, TouchToFillClosed, (bool), (override));
+#if BUILDFLAG(IS_ANDROID)
+  MOCK_METHOD(void, TriggerFormSubmission, (), (override));
+#endif
   MOCK_METHOD(void,
               AnnotateFieldsWithParsingResult,
               (const ParsingResult&),
diff --git a/components/password_manager/core/browser/password_manager_driver.h b/components/password_manager/core/browser/password_manager_driver.h
index 7024de88..63bf139 100644
--- a/components/password_manager/core/browser/password_manager_driver.h
+++ b/components/password_manager/core/browser/password_manager_driver.h
@@ -90,6 +90,11 @@
       bool is_password,
       const std::u16string& user_provided_credential) {}
 
+#if BUILDFLAG(IS_ANDROID)
+  // Triggers form submission on the last interacted web input element.
+  virtual void TriggerFormSubmission() {}
+#endif
+
   // Tells the driver to preview filling form with the |username| and
   // |password|.
   virtual void PreviewSuggestion(const std::u16string& username,
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.cc b/components/password_manager/core/browser/stub_password_manager_driver.cc
index 4c26ede..f91c367 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.cc
+++ b/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -26,6 +26,10 @@
                                                const std::u16string& password) {
 }
 
+#if BUILDFLAG(IS_ANDROID)
+void StubPasswordManagerDriver::TriggerFormSubmission() {}
+#endif
+
 void StubPasswordManagerDriver::PreviewSuggestion(
     const std::u16string& username,
     const std::u16string& password) {}
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.h b/components/password_manager/core/browser/stub_password_manager_driver.h
index ea4f7f1..802661f 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.h
+++ b/components/password_manager/core/browser/stub_password_manager_driver.h
@@ -29,6 +29,9 @@
   void GeneratedPasswordAccepted(const std::u16string& password) override;
   void FillSuggestion(const std::u16string& username,
                       const std::u16string& password) override;
+#if BUILDFLAG(IS_ANDROID)
+  void TriggerFormSubmission() override;
+#endif
   void PreviewSuggestion(const std::u16string& username,
                          const std::u16string& password) override;
   void ClearPreviewedForm() override;
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
index 8ab11817..fb1727e2 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -303,6 +303,38 @@
   return muted;
 }
 
+bool InsecureCredentialsManager::UnmuteCredential(
+    const CredentialView& credential) {
+  auto it = credentials_to_forms_.find(credential);
+  if (it == credentials_to_forms_.end())
+    return false;
+
+  // Unmute all matching compromised credentials from the store.
+  // For a match, all insecureity types saved in the store are unmuted.
+  // Return whether any credentials were unmuted.
+  const auto& saved_passwords = it->second.forms;
+  bool unmuted = false;
+
+  for (const PasswordForm& saved_password : saved_passwords) {
+    PasswordForm form_to_update = saved_password;
+    bool form_changed = false;
+    for (const auto& password_issue : saved_password.password_issues) {
+      if (password_issue.second.is_muted.value()) {
+        form_to_update.password_issues.insert_or_assign(
+            password_issue.first,
+            InsecurityMetadata(password_issue.second.create_time,
+                               IsMuted(false)));
+        form_changed = true;
+      }
+    }
+    if (form_changed) {
+      GetStoreFor(saved_password).UpdateLogin(form_to_update);
+      unmuted = true;
+    }
+  }
+  return unmuted;
+}
+
 bool InsecureCredentialsManager::UpdateCredential(
     const CredentialView& credential,
     const base::StringPiece password) {
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
index 280d9bd2..bbb06fc 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager.h
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -139,7 +139,7 @@
 struct CredentialMetadata;
 
 // This class provides clients with saved insecure credentials and possibility
-// to save new LeakedCredentials, edit/delete/mute insecure credentials and
+// to save new LeakedCredentials, edit/delete/[un]mute insecure credentials and
 // match insecure credentials with corresponding autofill::PasswordForms. It
 // supports an observer interface, and clients can register themselves to get
 // notified about changes to the list.
@@ -188,6 +188,10 @@
   // Returns whether the mute succeeded.
   bool MuteCredential(const CredentialView& credential);
 
+  // Attempts to unmute |credential| from the password store.
+  // Returns whether the unmute succeeded.
+  bool UnmuteCredential(const CredentialView& credential);
+
   // Returns a vector of currently insecure credentials.
   std::vector<CredentialWithPassword> GetInsecureCredentials() const;
 
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
index ef34481d..177bbb4 100644
--- a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
+++ b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -719,6 +719,99 @@
                   .is_muted.value());
 }
 
+TEST_F(InsecureCredentialsManagerTest, UnmuteCompromisedMutedCredential) {
+  PasswordForm password =
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
+  password.password_issues.insert(
+      {InsecureType::kLeaked, InsecurityMetadata(base::Time(), IsMuted(true))});
+
+  store().AddLogin(password);
+  RunUntilIdle();
+
+  CredentialWithPassword expected = MakeCompromisedCredential(
+      password, InsecureCredentialTypeFlags::kCredentialLeaked, true);
+
+  EXPECT_THAT(provider().GetInsecureCredentials(), ElementsAre(expected));
+  EXPECT_TRUE(provider().GetInsecureCredentials()[0].is_muted);
+
+  EXPECT_TRUE(provider().UnmuteCredential(expected));
+  RunUntilIdle();
+  EXPECT_FALSE(provider().GetInsecureCredentials()[0].is_muted);
+  EXPECT_FALSE(store()
+                   .stored_passwords()
+                   .at(kExampleCom)
+                   .back()
+                   .password_issues.at(InsecureType::kLeaked)
+                   .is_muted.value());
+}
+
+TEST_F(InsecureCredentialsManagerTest, UnmuteCompromisedNotMutedCredential) {
+  PasswordForm password =
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
+  password.password_issues.insert(
+      {InsecureType::kLeaked,
+       InsecurityMetadata(base::Time(), IsMuted(false))});
+
+  store().AddLogin(password);
+  RunUntilIdle();
+
+  CredentialWithPassword expected = MakeCompromisedCredential(
+      password, InsecureCredentialTypeFlags::kCredentialLeaked, false);
+
+  EXPECT_THAT(provider().GetInsecureCredentials(), ElementsAre(expected));
+  EXPECT_FALSE(provider().GetInsecureCredentials()[0].is_muted);
+
+  EXPECT_FALSE(provider().UnmuteCredential(expected));
+  RunUntilIdle();
+  EXPECT_FALSE(provider().GetInsecureCredentials()[0].is_muted);
+  EXPECT_FALSE(store()
+                   .stored_passwords()
+                   .at(kExampleCom)
+                   .back()
+                   .password_issues.at(InsecureType::kLeaked)
+                   .is_muted.value());
+}
+
+TEST_F(InsecureCredentialsManagerTest,
+       UnmuteCompromisedMutedCredentialWithMultipleInsecurityTypes) {
+  PasswordForm password =
+      MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
+  password.password_issues.insert(
+      {InsecureType::kLeaked, InsecurityMetadata(base::Time(), IsMuted(true))});
+  password.password_issues.insert(
+      {InsecureType::kPhished,
+       InsecurityMetadata(base::Time(), IsMuted(true))});
+
+  store().AddLogin(password);
+  RunUntilIdle();
+
+  CredentialWithPassword expected = MakeCompromisedCredential(
+      password,
+      InsecureCredentialTypeFlags::kCredentialLeaked |
+          InsecureCredentialTypeFlags::kCredentialPhished,
+      true);
+
+  EXPECT_THAT(provider().GetInsecureCredentials(), ElementsAre(expected));
+
+  EXPECT_TRUE(provider().GetInsecureCredentials()[0].is_muted);
+
+  EXPECT_TRUE(provider().UnmuteCredential(expected));
+  RunUntilIdle();
+  EXPECT_FALSE(provider().GetInsecureCredentials()[0].is_muted);
+  EXPECT_FALSE(store()
+                   .stored_passwords()
+                   .at(kExampleCom)
+                   .back()
+                   .password_issues.at(InsecureType::kLeaked)
+                   .is_muted.value());
+  EXPECT_FALSE(store()
+                   .stored_passwords()
+                   .at(kExampleCom)
+                   .back()
+                   .password_issues.at(InsecureType::kPhished)
+                   .is_muted.value());
+}
+
 TEST_F(InsecureCredentialsManagerTest, MuteCompromisedCredentialOnMutedIsNoOp) {
   PasswordForm password =
       MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
diff --git a/components/permissions/prediction_service/prediction_common.h b/components/permissions/prediction_service/prediction_common.h
index a5e7dcc..fdd557d 100644
--- a/components/permissions/prediction_service/prediction_common.h
+++ b/components/permissions/prediction_service/prediction_common.h
@@ -10,7 +10,6 @@
 
 namespace permissions {
 
-// TODO(andypaicu): when available, replace with actual URL.
 constexpr char kDefaultPredictionServiceUrl[] =
     "https://webpermissionpredictions.googleapis.com/v1:generatePredictions";
 
diff --git a/components/signin/internal/identity_manager/account_capabilities_constants.cc b/components/signin/internal/identity_manager/account_capabilities_constants.cc
index 44fe564..78be14e 100644
--- a/components/signin/internal/identity_manager/account_capabilities_constants.cc
+++ b/components/signin/internal/identity_manager/account_capabilities_constants.cc
@@ -4,6 +4,9 @@
 
 #include "components/signin/internal/identity_manager/account_capabilities_constants.h"
 
+const char kIsSubjectToParentalControlsCapabilityName[] =
+    "accountcapabilities/guydolldmfya";
+
 const char kCanOfferExtendedChromeSyncPromosCapabilityName[] =
     "accountcapabilities/gi2tklldmfya";
 
diff --git a/components/signin/internal/identity_manager/account_capabilities_constants.h b/components/signin/internal/identity_manager/account_capabilities_constants.h
index df8cb64..0e638dc6 100644
--- a/components/signin/internal/identity_manager/account_capabilities_constants.h
+++ b/components/signin/internal/identity_manager/account_capabilities_constants.h
@@ -7,5 +7,6 @@
 
 extern const char kCanOfferExtendedChromeSyncPromosCapabilityName[];
 extern const char kCanOfferExtendedChromeSyncPromosCapabilityPrefsPath[];
+extern const char kIsSubjectToParentalControlsCapabilityName[];
 
 #endif  // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_CAPABILITIES_CONSTANTS_H_
diff --git a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
index 083f841..e611eba7 100644
--- a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
+++ b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
@@ -108,8 +108,17 @@
       // should consider moving it to |SigninManager|.
       return token_service_->RefreshTokenHasError(
           primary_account_manager_->GetPrimaryAccountId(ConsentLevel::kSync));
-    case AccountConsistencyMethod::kDisabled:
     case AccountConsistencyMethod::kMirror:
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+      // TODO(crbug.com/1217645): Consider making this return false only for the
+      // main profile and return true, otherwise. This requires implementing
+      // ProfileOAuth2TokenServiceDelegateChromeOS::Revoke* and it's not clear
+      // what these functions should do.
+      return false;
+#else
+      return true;
+#endif
+    case AccountConsistencyMethod::kDisabled:
       return true;
   }
 }
@@ -118,11 +127,6 @@
 void PrimaryAccountMutatorImpl::RevokeSyncConsent(
     signin_metrics::ProfileSignout source_metric,
     signin_metrics::SignoutDelete delete_metric) {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // On Lacros with Mirror, revoking consent is not supported yet.
-  // TODO(https://crbug.com/1260291): Remove this when it is supported.
-  CHECK_NE(account_consistency_, AccountConsistencyMethod::kMirror);
-#endif
   DCHECK(primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync));
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -141,12 +145,6 @@
   if (!primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSignin))
     return false;
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // On Lacros with Mirror, signout is not supported yet.
-  // TODO(https://crbug.com/1260291): Remove this when signout is supported.
-  CHECK_NE(account_consistency_, AccountConsistencyMethod::kMirror);
-#endif
-
   primary_account_manager_->ClearPrimaryAccount(source_metric, delete_metric);
   return true;
 }
diff --git a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
index 36c6081..24abd00 100644
--- a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -448,13 +448,9 @@
 // consistency method.
 TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount) {
   const signin::AccountConsistencyMethod kTestedAccountConsistencyMethods[] = {
-    signin::AccountConsistencyMethod::kDisabled,
-#if !BUILDFLAG(IS_CHROMEOS_LACROS)
-    // Signout is not supported with Mirror on Lacros.
-    // TODO(https://crbug.com/1260291): Re-enable when signout is supported.
-    signin::AccountConsistencyMethod::kMirror,
-#endif
-    signin::AccountConsistencyMethod::kDice,
+      signin::AccountConsistencyMethod::kDisabled,
+      signin::AccountConsistencyMethod::kMirror,
+      signin::AccountConsistencyMethod::kDice,
   };
   for (signin::AccountConsistencyMethod account_consistency_method :
        kTestedAccountConsistencyMethods) {
@@ -470,15 +466,16 @@
 }
 
 // Test that revoking sync consent when Mirror account consistency is enabled
-// clears the primary account.
-#if !BUILDFLAG(IS_CHROMEOS_LACROS)
-// Revoking sync consent not supported with Mirror on Lacros.
-// TODO(https://crbug.com/1260291): Re-enable when it is supported.
+// clears the primary account (except for lacros).
 TEST_F(PrimaryAccountMutatorTest, RevokeSyncConsent_MirrorConsistency) {
   RunRevokeSyncConsentTest(signin::AccountConsistencyMethod::kMirror,
-                           RemoveAccountExpectation::kRemoveAll);
-}
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+                           RemoveAccountExpectation::kKeepAll
+#else
+                           RemoveAccountExpectation::kRemoveAll
 #endif
+  );
+}
 
 // Test that revoking the sync consent when DICE account consistency is
 // enabled does not clear the primary account.
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc
index 75f4ae2..f126c1d 100644
--- a/components/user_manager/known_user.cc
+++ b/components/user_manager/known_user.cc
@@ -321,18 +321,23 @@
   SetPath(account_id, path, base::Value(in_value));
 }
 
-bool KnownUser::GetIntegerPref(const AccountId& account_id,
-                               const std::string& path,
-                               int* out_value) {
+absl::optional<int> KnownUser::FindIntPath(const AccountId& account_id,
+                                           base::StringPiece path) const {
   const base::Value* user_pref_dict = FindPrefs(account_id);
   if (!user_pref_dict)
-    return false;
-  absl::optional<int> optional_value = user_pref_dict->FindIntPath(path);
+    return absl::nullopt;
 
-  if (out_value && optional_value.has_value())
-    *out_value = optional_value.value();
+  return user_pref_dict->FindIntPath(path);
+}
 
-  return optional_value.has_value();
+bool KnownUser::GetIntegerPrefForTest(const AccountId& account_id,
+                                      const std::string& path,
+                                      int* out_value) {
+  auto opt_val = FindIntPath(account_id, path);
+  if (out_value && opt_val.has_value())
+    *out_value = opt_val.value();
+
+  return opt_val.has_value();
 }
 
 void KnownUser::SetIntegerPref(const AccountId& account_id,
@@ -581,8 +586,9 @@
   SetIntegerPref(account_id, kReauthReasonKey, reauth_reason);
 }
 
-bool KnownUser::FindReauthReason(const AccountId& account_id, int* out_value) {
-  return GetIntegerPref(account_id, kReauthReasonKey, out_value);
+absl::optional<int> KnownUser::FindReauthReason(
+    const AccountId& account_id) const {
+  return FindIntPath(account_id, kReauthReasonKey);
 }
 
 void KnownUser::SetChallengeResponseKeys(const AccountId& account_id,
@@ -667,10 +673,7 @@
 }
 
 int KnownUser::GetUserPinLength(const AccountId& account_id) {
-  int pin_length = 0;
-  if (GetIntegerPref(account_id, kPinAutosubmitLength, &pin_length))
-    return pin_length;
-  return 0;
+  return FindIntPath(account_id, kPinAutosubmitLength).value_or(0);
 }
 
 bool KnownUser::PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
@@ -821,7 +824,11 @@
   // Local State may not be initialized in tests.
   if (!local_state)
     return false;
-  return KnownUser(local_state).GetIntegerPref(account_id, path, out_value);
+  absl::optional<int> val =
+      KnownUser(local_state).FindIntPath(account_id, path);
+  if (out_value && val.has_value())
+    *out_value = val.value();
+  return val.has_value();
 }
 
 void SetIntegerPref(const AccountId& account_id,
@@ -1006,22 +1013,6 @@
   return KnownUser(local_state).ClearProfileRequiresPolicy(account_id);
 }
 
-void UpdateReauthReason(const AccountId& account_id, const int reauth_reason) {
-  PrefService* local_state = GetLocalStateLegacy();
-  // Local State may not be initialized in tests.
-  if (!local_state)
-    return;
-  return KnownUser(local_state).UpdateReauthReason(account_id, reauth_reason);
-}
-
-bool FindReauthReason(const AccountId& account_id, int* out_value) {
-  PrefService* local_state = GetLocalStateLegacy();
-  // Local State may not be initialized in tests.
-  if (!local_state)
-    return false;
-  return KnownUser(local_state).FindReauthReason(account_id, out_value);
-}
-
 void SetLastOnlineSignin(const AccountId& account_id, base::Time time) {
   PrefService* local_state = GetLocalStateLegacy();
   // Local State may not be initialized in tests.
diff --git a/components/user_manager/known_user.h b/components/user_manager/known_user.h
index bb8c0cb3..8e0ec7be 100644
--- a/components/user_manager/known_user.h
+++ b/components/user_manager/known_user.h
@@ -87,11 +87,16 @@
                       const std::string& path,
                       const bool in_value);
 
+  // Return absl::nullopt if the value is not found or doesn't have the int
+  // type.
+  absl::optional<int> FindIntPath(const AccountId& account_id,
+                                  base::StringPiece path) const;
+
   // Returns true if |account_id| preference by |path| does exist,
   // fills in |out_value|. Otherwise returns false.
-  bool GetIntegerPref(const AccountId& account_id,
-                      const std::string& path,
-                      int* out_value);
+  bool GetIntegerPrefForTest(const AccountId& account_id,
+                             const std::string& path,
+                             int* out_value);
 
   // Updates user's identified by |account_id| integer preference |path|.
   void SetIntegerPref(const AccountId& account_id,
@@ -173,9 +178,8 @@
   void UpdateReauthReason(const AccountId& account_id, const int reauth_reason);
 
   // Returns the reason why the user with |account_id| has to go through the
-  // re-auth flow. Returns true if such a reason was recorded or false
-  // otherwise.
-  bool FindReauthReason(const AccountId& account_id, int* out_value);
+  // re-auth flow. Returns absl::nullopt if value is not set.
+  absl::optional<int> FindReauthReason(const AccountId& account_id) const;
 
   // Setter and getter for the information about challenge-response keys that
   // can be used by this user to authenticate. The getter returns a null value
@@ -302,21 +306,6 @@
 
 // Returns true if |account_id| preference by |path| does exist,
 // fills in |out_value|. Otherwise returns false.
-// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetIntegerPref
-// instead.
-bool USER_MANAGER_EXPORT GetIntegerPref(const AccountId& account_id,
-                                        const std::string& path,
-                                        int* out_value);
-
-// Updates user's identified by |account_id| integer preference |path|.
-// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetIntegerPref
-// instead.
-void USER_MANAGER_EXPORT SetIntegerPref(const AccountId& account_id,
-                                        const std::string& path,
-                                        const int in_value);
-
-// Returns true if |account_id| preference by |path| does exist,
-// fills in |out_value|. Otherwise returns false.
 // TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetPref instead.
 bool USER_MANAGER_EXPORT GetPref(const AccountId& account_id,
                                  const std::string& path,
@@ -415,20 +404,6 @@
 void USER_MANAGER_EXPORT
 ClearProfileRequiresPolicy(const AccountId& account_id);
 
-// Saves why the user has to go through re-auth flow.
-// TODO(https://crbug.com/1150434): Deprecated, use
-// KnownUser::UpdateReauthReason instead.
-void USER_MANAGER_EXPORT UpdateReauthReason(const AccountId& account_id,
-                                            const int reauth_reason);
-
-// Returns the reason why the user with |account_id| has to go through the
-// re-auth flow. Returns true if such a reason was recorded or false
-// otherwise.
-// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::FindReauthReason
-// instead.
-bool USER_MANAGER_EXPORT FindReauthReason(const AccountId& account_id,
-                                          int* out_value);
-
 // TODO(https://crbug.com/1150434): Deprecated, use
 // KnownUser::SetLastOnlineSignin instead.
 void USER_MANAGER_EXPORT SetLastOnlineSignin(const AccountId& account_id,
diff --git a/components/user_manager/known_user_unittest.cc b/components/user_manager/known_user_unittest.cc
index 48ddeaa..29d6b7ec 100644
--- a/components/user_manager/known_user_unittest.cc
+++ b/components/user_manager/known_user_unittest.cc
@@ -415,17 +415,10 @@
 
 TEST_F(KnownUserTest, ReauthReason) {
   KnownUser known_user(local_state());
-  {
-    int auth_reason;
-    EXPECT_FALSE(known_user.FindReauthReason(kDefaultAccountId, &auth_reason));
-  }
+  EXPECT_FALSE(known_user.FindReauthReason(kDefaultAccountId).has_value());
 
   known_user.UpdateReauthReason(kDefaultAccountId, 3);
-  {
-    int auth_reason;
-    EXPECT_TRUE(known_user.FindReauthReason(kDefaultAccountId, &auth_reason));
-    EXPECT_EQ(auth_reason, 3);
-  }
+  EXPECT_EQ(known_user.FindReauthReason(kDefaultAccountId), 3);
 }
 
 TEST_F(KnownUserTest, ChallengeResponseKeys) {
@@ -611,7 +604,7 @@
   using PrefTypeForReading = int;
 
   static constexpr auto SetFunc = &KnownUser::SetIntegerPref;
-  static constexpr auto GetFunc = &KnownUser::GetIntegerPref;
+  static constexpr auto GetFunc = &KnownUser::GetIntegerPrefForTest;
 
   static PrefType CreatePrefValue() { return 7; }
   static bool CheckPrefValue(PrefTypeForReading read_value) {
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 82671457..12c7366 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -487,8 +487,6 @@
       sources += [
         "display_embedder/skia_output_device_vulkan_secondary_cb.cc",
         "display_embedder/skia_output_device_vulkan_secondary_cb.h",
-        "display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc",
-        "display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h",
       ]
     }
 
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 9e0de84..10b219a0 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -599,7 +599,10 @@
       SurfaceAggregator::ExtraPassForReadbackOption::kNone;
   if (output_surface_->capabilities().root_is_vulkan_secondary_command_buffer) {
     extra_pass_option =
-        SurfaceAggregator::ExtraPassForReadbackOption::kAddPassForReadback;
+        base::FeatureList::IsEnabled(features::kWebViewVulkanIntermediateBuffer)
+            ? SurfaceAggregator::ExtraPassForReadbackOption::kAlwaysAddPass
+            : SurfaceAggregator::ExtraPassForReadbackOption::
+                  kAddPassForReadback;
   }
   aggregator_ = std::make_unique<SurfaceAggregator>(
       surface_manager_, resource_provider_.get(), output_partial_list,
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index c897c2c..fad56c3 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -1079,6 +1079,11 @@
     }
   }
 
+  if (extra_pass_for_readback_option_ ==
+      ExtraPassForReadbackOption::kAlwaysAddPass) {
+    needs_readback_pass = true;
+  }
+
   if (needs_readback_pass != last_frame_had_readback_pass_)
     root_render_pass->damage_rect = output_rect;
 
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 34e9a39..4910e6b5 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -49,6 +49,8 @@
     kNone,
     // Add an extra render pass only if readback is needed.
     kAddPassForReadback,
+    // Always add an extra pass. Useful for debugging.
+    kAlwaysAddPass,
   };
 
   // Interface that can modify the aggregated CompositorFrame to annotate it.
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
deleted file mode 100644
index aaca9ec..0000000
--- a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h"
-
-#include <utility>
-
-#include "components/viz/common/gpu/vulkan_context_provider.h"
-#include "gpu/command_buffer/service/skia_utils.h"
-#include "gpu/vulkan/vulkan_device_queue.h"
-#include "gpu/vulkan/vulkan_function_pointers.h"
-#include "skia/ext/legacy_display_globals.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkDeferredDisplayList.h"
-#include "third_party/skia/include/core/SkSurface.h"
-#include "third_party/skia/include/core/SkSurfaceCharacterization.h"
-#include "third_party/skia/include/gpu/GrBackendSurface.h"
-#include "third_party/skia/include/gpu/GrDirectContext.h"
-#include "third_party/skia/src/gpu/vk/GrVkSecondaryCBDrawContext.h"
-#include "ui/gfx/presentation_feedback.h"
-#include "ui/gfx/swap_result.h"
-
-namespace viz {
-
-SkiaOutputDeviceVulkanSecondaryCBOffscreen::
-    SkiaOutputDeviceVulkanSecondaryCBOffscreen(
-        scoped_refptr<gpu::SharedContextState> context_state,
-        gpu::MemoryTracker* memory_tracker,
-        DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
-    : SkiaOutputDeviceOffscreen(std::move(context_state),
-                                gfx::SurfaceOrigin::kTopLeft,
-                                /*has_alpha=*/true,
-                                memory_tracker,
-                                std::move(did_swap_buffer_complete_callback)) {
-  DCHECK(context_state_->vk_context_provider());
-  capabilities_.pending_swap_params.max_pending_swaps = 1;
-  capabilities_.preserve_buffer_content = false;
-  capabilities_.supports_post_sub_buffer = false;
-}
-
-SkiaOutputDeviceVulkanSecondaryCBOffscreen::
-    ~SkiaOutputDeviceVulkanSecondaryCBOffscreen() = default;
-
-SkSurface* SkiaOutputDeviceVulkanSecondaryCBOffscreen::BeginPaint(
-    bool allocate_frame_buffer,
-    std::vector<GrBackendSemaphore>* end_semaphores) {
-  SkSurface* sk_surface = SkiaOutputDeviceOffscreen::BeginPaint(
-      allocate_frame_buffer, end_semaphores);
-  sk_surface->getCanvas()->clear(SK_ColorTRANSPARENT);
-  return sk_surface;
-}
-
-void SkiaOutputDeviceVulkanSecondaryCBOffscreen::SwapBuffers(
-    BufferPresentedCallback feedback,
-    OutputSurfaceFrame frame) {
-  StartSwapBuffers(std::move(feedback));
-
-  auto format_index = static_cast<int>(format_);
-  const auto& sk_color_type = capabilities_.sk_color_types[format_index];
-  DCHECK(sk_color_type != kUnknown_SkColorType)
-      << "SkColorType is invalid for format: " << format_index;
-  sk_sp<SkImage> sk_image = SkImage::MakeFromTexture(
-      context_state_->vk_context_provider()->GetGrContext(), backend_texture_,
-      kTopLeft_GrSurfaceOrigin, sk_color_type, kPremul_SkAlphaType,
-      sk_color_space_);
-  gfx::SwapResult result = gfx::SwapResult::SWAP_ACK;
-  if (sk_image) {
-    SkPaint paint;
-    paint.setBlendMode(SkBlendMode::kSrcOver);
-    context_state_->vk_context_provider()
-        ->GetGrSecondaryCBDrawContext()
-        ->getCanvas()
-        ->drawImage(sk_image, 0, 0, SkSamplingOptions(), &paint);
-    context_state_->vk_context_provider()
-        ->GetGrSecondaryCBDrawContext()
-        ->flush();
-  } else {
-    result = gfx::SwapResult::SWAP_FAILED;
-  }
-
-  FinishSwapBuffers(gfx::SwapCompletionResult(result),
-                    gfx::Size(size_.width(), size_.height()), std::move(frame));
-}
-
-}  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h
deleted file mode 100644
index f39135fc..0000000
--- a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_
-#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_
-
-#include <vector>
-
-#include "components/viz/service/display_embedder/skia_output_device_offscreen.h"
-#include "gpu/command_buffer/service/shared_context_state.h"
-
-namespace viz {
-
-// Draw into an offscreen buffer which is then drawn to into the secondary
-// command buffer. This is meant to for debugging direct compositing with
-// secondary command buffers.
-class SkiaOutputDeviceVulkanSecondaryCBOffscreen final
-    : public SkiaOutputDeviceOffscreen {
- public:
-  SkiaOutputDeviceVulkanSecondaryCBOffscreen(
-      scoped_refptr<gpu::SharedContextState> context_state,
-      gpu::MemoryTracker* memory_tracker,
-      DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
-  ~SkiaOutputDeviceVulkanSecondaryCBOffscreen() override;
-
-  SkSurface* BeginPaint(
-      bool allocate_frame_buffer,
-      std::vector<GrBackendSemaphore>* end_semaphores) override;
-  void SwapBuffers(BufferPresentedCallback feedback,
-                   OutputSurfaceFrame frame) override;
-};
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 4ac2367..26606fbc4 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -64,7 +64,6 @@
 #include "gpu/vulkan/vulkan_util.h"
 #if BUILDFLAG(IS_ANDROID)
 #include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb.h"
-#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h"
 #endif
 #endif
 
@@ -1575,17 +1574,9 @@
 
 #if BUILDFLAG(IS_ANDROID)
   if (vulkan_context_provider_->GetGrSecondaryCBDrawContext()) {
-    if (base::FeatureList::IsEnabled(
-            features::kWebViewVulkanIntermediateBuffer)) {
-      output_device_ =
-          std::make_unique<SkiaOutputDeviceVulkanSecondaryCBOffscreen>(
-              context_state_, shared_gpu_deps_->memory_tracker(),
-              GetDidSwapBuffersCompleteCallback());
-    } else {
-      output_device_ = std::make_unique<SkiaOutputDeviceVulkanSecondaryCB>(
-          vulkan_context_provider_, shared_gpu_deps_->memory_tracker(),
-          GetDidSwapBuffersCompleteCallback());
-    }
+    output_device_ = std::make_unique<SkiaOutputDeviceVulkanSecondaryCB>(
+        vulkan_context_provider_, shared_gpu_deps_->memory_tracker(),
+        GetDidSwapBuffersCompleteCallback());
     return true;
   }
 #endif
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 47496f2..cf3e0ba 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -109,11 +109,6 @@
 void DumpAccessibilityTestBase::ChooseFeatures(
     std::vector<base::Feature>* enabled_features,
     std::vector<base::Feature>* disabled_features) {
-
-  // Enable exposing "display: none" nodes to the browser process for testing.
-  enabled_features->emplace_back(
-      features::kEnableAccessibilityExposeDisplayNone);
-
   // For the best test coverage during development of this feature, enable the
   // code that expposes document markers on AXInlineTextBox objects and the
   // corresponding code in AXPosition on the browser that collects those
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index 11d6ca12..1a39830 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -31,6 +31,7 @@
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_navigation_policy.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
@@ -4973,6 +4974,11 @@
 // That is, the auction limit count is preserved due to bfcache.
 IN_PROC_BROWSER_TEST_F(InterestGroupAuctionLimitBrowserTest,
                        MAYBE_NavigatingWithBfcachePreservesAuctionLimits) {
+  if (!IsBackForwardCacheEnabled()) {
+    // This test requires back/forward cache. Skip this test when the
+    // back/forward cache is disabled.
+    return;
+  }
   const GURL test_url = https_server_->GetURL("a.test", "/echo");
   ASSERT_TRUE(NavigateToURL(shell(), test_url));
   const url::Origin test_origin = url::Origin::Create(test_url);
diff --git a/content/browser/prerender/prerender_attributes.cc b/content/browser/prerender/prerender_attributes.cc
index caddceb..3d5bf55 100644
--- a/content/browser/prerender/prerender_attributes.cc
+++ b/content/browser/prerender/prerender_attributes.cc
@@ -25,7 +25,9 @@
     int initiator_process_id,
     absl::optional<blink::LocalFrameToken> initiator_frame_token,
     ukm::SourceId initiator_ukm_id,
-    ui::PageTransition transition_type)
+    ui::PageTransition transition_type,
+    absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+        url_match_predicate)
     : prerendering_url(prerendering_url),
       trigger_type(trigger_type),
       embedder_histogram_suffix(embedder_histogram_suffix),
@@ -35,7 +37,8 @@
       initiator_process_id(initiator_process_id),
       initiator_frame_token(std::move(initiator_frame_token)),
       initiator_ukm_id(initiator_ukm_id),
-      transition_type(transition_type) {}
+      transition_type(transition_type),
+      url_match_predicate(std::move(url_match_predicate)) {}
 
 PrerenderAttributes::~PrerenderAttributes() = default;
 
@@ -52,6 +55,7 @@
       initiator_process_id(attributes.initiator_process_id),
       initiator_frame_token(attributes.initiator_frame_token),
       initiator_ukm_id(attributes.initiator_ukm_id),
-      transition_type(attributes.transition_type) {}
+      transition_type(attributes.transition_type),
+      url_match_predicate(attributes.url_match_predicate) {}
 
 }  // namespace content
diff --git a/content/browser/prerender/prerender_attributes.h b/content/browser/prerender/prerender_attributes.h
index ad86a0e..af364802 100644
--- a/content/browser/prerender/prerender_attributes.h
+++ b/content/browser/prerender/prerender_attributes.h
@@ -29,7 +29,10 @@
       int initiator_process_id,
       absl::optional<blink::LocalFrameToken> initiator_frame_token,
       ukm::SourceId initiator_ukm_id,
-      ui::PageTransition transition_type);
+      ui::PageTransition transition_type,
+      absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+          url_match_predicate);
+
   ~PrerenderAttributes();
   PrerenderAttributes(const PrerenderAttributes&);
   PrerenderAttributes& operator=(const PrerenderAttributes&) = delete;
@@ -67,6 +70,11 @@
 
   ui::PageTransition transition_type;
 
+  // Triggers can specify their own pedicates judging whether two URLs are
+  // considered as pointing to the same destination.
+  absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+      url_match_predicate;
+
   // Serialises this struct into a trace.
   void WriteIntoTrace(perfetto::TracedValue trace_context) const;
 };
diff --git a/content/browser/prerender/prerender_host.cc b/content/browser/prerender/prerender_host.cc
index 437fea2..38f5dd6 100644
--- a/content/browser/prerender/prerender_host.cc
+++ b/content/browser/prerender/prerender_host.cc
@@ -642,8 +642,12 @@
   // initial and activation prerender navigations, as the PrerenderHost
   // selection would have already checked for matching values. Adding a DCHECK
   // here to be safe.
-  DCHECK_EQ(potential_activation.url, common_params_->url);
-
+  if (attributes_.url_match_predicate) {
+    DCHECK(
+        attributes_.url_match_predicate.value().Run(potential_activation.url));
+  } else {
+    DCHECK_EQ(potential_activation.url, common_params_->url);
+  }
   if (potential_activation.initiator_origin !=
       common_params_->initiator_origin) {
     return false;
@@ -801,6 +805,18 @@
   common_params_ = navigation->common_params().Clone();
 }
 
+bool PrerenderHost::IsUrlMatch(const GURL& url) const {
+  // If the trigger defines its predicate, respect it.
+  if (attributes_.url_match_predicate) {
+    // Triggers are not allowed to treat a cross-origin url a matched url. It
+    // would cause security risks.
+    if (!url::IsSameOriginWith(attributes_.prerendering_url, url))
+      return false;
+    return attributes_.url_match_predicate.value().Run(url);
+  }
+  return GetInitialUrl() == url;
+}
+
 void PrerenderHost::Cancel(FinalStatus status) {
   TRACE_EVENT("navigation", "PrerenderHost::Cancel", "final_status", status);
   // Already cancelled.
diff --git a/content/browser/prerender/prerender_host.h b/content/browser/prerender/prerender_host.h
index 65e5a39..229a8e4f 100644
--- a/content/browser/prerender/prerender_host.h
+++ b/content/browser/prerender/prerender_host.h
@@ -159,6 +159,10 @@
   void SetInitialNavigation(NavigationRequest* navigation);
   absl::optional<int64_t> GetInitialNavigationId() const;
 
+  // Returns true if the given `url` indicates the same destination to the
+  // initial_url.
+  bool IsUrlMatch(const GURL& url) const;
+
   // Returns absl::nullopt iff prerendering is initiated by the browser (not by
   // a renderer using Speculation Rules API).
   absl::optional<url::Origin> initiator_origin() const {
diff --git a/content/browser/prerender/prerender_host_registry.cc b/content/browser/prerender/prerender_host_registry.cc
index 5b9398e..ef85dbd 100644
--- a/content/browser/prerender/prerender_host_registry.cc
+++ b/content/browser/prerender/prerender_host_registry.cc
@@ -407,9 +407,10 @@
 
   // Find an available host for the navigation URL.
   PrerenderHost* host = nullptr;
-  for (const auto& iter : prerender_host_by_frame_tree_node_id_) {
-    if (iter.second->GetInitialUrl() == navigation_request.GetURL()) {
-      host = iter.second.get();
+  for (const auto& [_, it_prerender_host] :
+       prerender_host_by_frame_tree_node_id_) {
+    if (it_prerender_host->IsUrlMatch(navigation_request.GetURL())) {
+      host = it_prerender_host.get();
       break;
     }
   }
diff --git a/content/browser/prerender/prerender_host_registry_unittest.cc b/content/browser/prerender/prerender_host_registry_unittest.cc
index 3756203f..2be8b918 100644
--- a/content/browser/prerender/prerender_host_registry_unittest.cc
+++ b/content/browser/prerender/prerender_host_registry_unittest.cc
@@ -51,7 +51,8 @@
       url, trigger_type, embedder_histogram_suffix, Referrer(),
       rfh->GetLastCommittedOrigin(), rfh->GetLastCommittedURL(),
       rfh->GetProcess()->GetID(), rfh->GetFrameToken(),
-      rfh->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK);
+      rfh->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK,
+      /*url_match_predicate=*/absl::nullopt);
 }
 
 // This definition is needed because this constant is odr-used in gtest macros.
diff --git a/content/browser/prerender/prerender_host_unittest.cc b/content/browser/prerender/prerender_host_unittest.cc
index e43f475..48341091 100644
--- a/content/browser/prerender/prerender_host_unittest.cc
+++ b/content/browser/prerender/prerender_host_unittest.cc
@@ -115,7 +115,21 @@
       /*embedder_histogram_suffix=*/"", Referrer(),
       rfh->GetLastCommittedOrigin(), rfh->GetLastCommittedURL(),
       rfh->GetProcess()->GetID(), rfh->GetFrameToken(),
-      rfh->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK);
+      rfh->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK,
+      /*url_match_predicate=*/absl::nullopt);
+}
+
+PrerenderAttributes GeneratePrerenderAttributesWithPredicate(
+    const GURL& url,
+    RenderFrameHostImpl* rfh,
+    base::RepeatingCallback<bool(const GURL&)> url_match_predicate) {
+  return PrerenderAttributes(
+      url, PrerenderTriggerType::kSpeculationRule,
+      /*embedder_histogram_suffix=*/"", Referrer(),
+      rfh->GetLastCommittedOrigin(), rfh->GetLastCommittedURL(),
+      rfh->GetProcess()->GetID(), rfh->GetFrameToken(),
+      rfh->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK,
+      std::move(url_match_predicate));
 }
 
 class TestWebContentsDelegate : public WebContentsDelegate {
@@ -450,5 +464,29 @@
 }
 #endif
 
+TEST_F(PrerenderHostTest, UrlMatchPredicate) {
+  std::unique_ptr<TestWebContents> web_contents =
+      CreateWebContents(GURL("https://example.com/"));
+  const GURL kPrerenderingUrl = GURL("https://example.com/empty.html");
+  RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame();
+  PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry();
+  base::RepeatingCallback callback =
+      base::BindRepeating([](const GURL&) { return true; });
+  const int prerender_frame_tree_node_id = registry->CreateAndStartHost(
+      GeneratePrerenderAttributesWithPredicate(kPrerenderingUrl, initiator_rfh,
+                                               callback),
+      *web_contents);
+  PrerenderHost* prerender_host =
+      registry->FindNonReservedHostById(prerender_frame_tree_node_id);
+  ASSERT_NE(prerender_host, nullptr);
+  const GURL kActivatedUrl = GURL("https://example.com/empty.html?activate");
+  ASSERT_NE(kActivatedUrl, kPrerenderingUrl);
+  EXPECT_TRUE(prerender_host->IsUrlMatch(kActivatedUrl));
+  // Even if the predicate always returns true, a cross-origin url shouldn't be
+  // able to activate a prerendered page.
+  EXPECT_FALSE(
+      prerender_host->IsUrlMatch(GURL("https://example2.com/empty.html")));
+}
+
 }  // namespace
 }  // namespace content
diff --git a/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
index fe119f40..de338b2 100644
--- a/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -289,7 +289,14 @@
 
 using ScrollThroughputBrowserTest = ScrollLatencyBrowserTest;
 
-IN_PROC_BROWSER_TEST_F(ScrollThroughputBrowserTest, ScrollThroughputMetrics) {
+// https://crbug.com/1067492. Flaky on Android.
+#if BUILDFLAG(IS_ANDROID)
+#define MAYBE_ScrollThroughputMetrics DISABLED_ScrollThroughputMetrics
+#else
+#define MAYBE_ScrollThroughputMetrics ScrollThroughputMetrics
+#endif
+IN_PROC_BROWSER_TEST_F(ScrollThroughputBrowserTest,
+                       MAYBE_ScrollThroughputMetrics) {
   LoadURL();
   auto scroll_update_watcher = std::make_unique<InputMsgWatcher>(
       GetWidgetHost(), blink::WebInputEvent::Type::kGestureScrollEnd);
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index eddc413f..8b92185 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -20,6 +20,7 @@
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_process_host_internal_observer.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_navigation_policy.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -1864,6 +1865,11 @@
 // that is no longer discoverable via FromID, while handling the deletion of a
 // subframe. One way this can occur is during bfcache eviction.
 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ForEachFrameNestedFrameDeletion) {
+  if (!IsBackForwardCacheEnabled()) {
+    // This test requires back/forward cache. Skip this test when the
+    // back/forward cache is disabled.
+    return;
+  }
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Ensure all sites get dedicated processes during the test.
diff --git a/content/browser/speculation_rules/speculation_host_impl.cc b/content/browser/speculation_rules/speculation_host_impl.cc
index 6b87ac6..f783c02 100644
--- a/content/browser/speculation_rules/speculation_host_impl.cc
+++ b/content/browser/speculation_rules/speculation_host_impl.cc
@@ -137,7 +137,8 @@
             /*embedder_histogram_suffix=*/"", Referrer(*(it->referrer)),
             rfhi->GetLastCommittedOrigin(), rfhi->GetLastCommittedURL(),
             rfhi->GetProcess()->GetID(), rfhi->GetFrameToken(),
-            rfhi->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK),
+            rfhi->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK,
+            /*url_match_predicate=*/absl::nullopt),
         *web_contents);
     if (prerender_host_id != RenderFrameHost::kNoFrameTreeNodeId)
       started_prerender_host_ids_.insert(prerender_host_id);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index be93839..5b18a31 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -9259,13 +9259,15 @@
     const GURL& prerendering_url,
     PrerenderTriggerType trigger_type,
     const std::string& embedder_histogram_suffix,
-    ui::PageTransition page_transition) {
+    ui::PageTransition page_transition,
+    absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+        url_match_predicate) {
   PrerenderAttributes attributes(
       prerendering_url, trigger_type, embedder_histogram_suffix,
       content::Referrer(), /*initiator_origin=*/absl::nullopt, prerendering_url,
       content::ChildProcessHost::kInvalidUniqueID,
       /*initiator_frame_token=*/absl::nullopt, ukm::kInvalidSourceId,
-      page_transition);
+      page_transition, url_match_predicate);
   int frame_tree_node_id =
       GetPrerenderHostRegistry()->CreateAndStartHost(attributes, *this);
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 5a4165a..9b2e32f 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -856,7 +856,9 @@
       const GURL& prerendering_url,
       PrerenderTriggerType trigger_type,
       const std::string& embedder_histogram_suffix,
-      ui::PageTransition page_transition) override;
+      ui::PageTransition page_transition,
+      absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+          url_match_predicate = absl::nullopt) override;
 
   // NavigatorDelegate ---------------------------------------------------------
 
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index 8f5bed8..59024bc 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -21,6 +21,7 @@
 #include "content/browser/loader/content_security_notifier.h"
 #include "content/browser/renderer_host/code_cache_host_impl.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
+#include "content/browser/renderer_host/private_network_access_util.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/service_worker/service_worker_container_host.h"
 #include "content/browser/service_worker/service_worker_main_resource_handle.h"
@@ -43,6 +44,7 @@
 #include "net/base/isolation_info.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/cpp/cross_origin_embedder_policy.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "services/network/public/mojom/blocked_by_response_reason.mojom.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "third_party/blink/public/common/features.h"
@@ -237,9 +239,10 @@
     return;
   }
 
-  // If this is a nested worker, there is no creator frame.
   RenderFrameHostImpl* creator_render_frame_host = nullptr;
+  DedicatedWorkerHost* creator_worker = nullptr;
   if (creator_render_frame_host_id_) {
+    // This is not a nested worker, it has a creator frame.
     creator_render_frame_host =
         RenderFrameHostImpl::FromID(*creator_render_frame_host_id_);
     if (!creator_render_frame_host) {
@@ -247,8 +250,29 @@
           script_url, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
       return;
     }
+  } else {
+    // The creator of this worker is a dedicated worker.
+    DCHECK(creator_worker_token_);
+
+    creator_worker =
+        service_->GetDedicatedWorkerHostFromToken(*creator_worker_token_);
+    if (!creator_worker) {
+      ScriptLoadStartFailed(
+          script_url, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+      return;
+    }
   }
 
+  // At this point there is either a creator frame or a creator worker.
+  //
+  // This may change at some point in the future if dedicated workers can be
+  // nested inside shared workers, as the HTML spec dictates. For now, nesting
+  // is only supported for dedicated workers inside dedicated workers, so the
+  // following invariant holds. If and when this changes, conditionals below
+  // should be revisited to account for the novel possibility of a creator
+  // shared worker.
+  DCHECK_NE(creator_render_frame_host == nullptr, creator_worker == nullptr);
+
   // Set if the subresource loader factories support file URLs so that we can
   // recreate the factories after Network Service crashes.
   // TODO(nhiroki): Currently this flag is calculated based on the request
@@ -268,25 +292,20 @@
       service_worker_handle_->set_parent_container_host(
           creator_render_frame_host->GetLastCommittedServiceWorkerHost());
     } else {
-      // The creator of this worker is a dedicated worker.
-      DCHECK(creator_worker_token_);
-
-      DedicatedWorkerHost* creator_worker =
-          service_->GetDedicatedWorkerHostFromToken(
-              creator_worker_token_.value());
-      if (!creator_worker) {
-        ScriptLoadStartFailed(
-            script_url, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
-        return;
-      }
-
       base::WeakPtr<ServiceWorkerContainerHost> creator_container_host =
           creator_worker->service_worker_handle()->container_host();
-
       service_worker_handle_->set_parent_container_host(creator_container_host);
     }
   }
 
+  network::mojom::ClientSecurityStatePtr client_security_state;
+  if (creator_render_frame_host) {
+    client_security_state =
+        creator_render_frame_host->BuildClientSecurityState();
+  } else {
+    client_security_state = creator_worker->client_security_state()->Clone();
+  }
+
   // Get a storage domain.
   auto partition_domain =
       nearest_ancestor_render_frame_host->GetSiteInstance()->GetPartitionDomain(
@@ -298,7 +317,8 @@
       nearest_ancestor_render_frame_host->ComputeSiteForCookies(),
       creator_origin_, storage_key_,
       nearest_ancestor_render_frame_host->GetIsolationInfoForSubresources(),
-      credentials_mode, std::move(outside_fetch_client_settings_object),
+      std::move(client_security_state), credentials_mode,
+      std::move(outside_fetch_client_settings_object),
       network::mojom::RequestDestination::kWorker,
       storage_partition_impl->GetServiceWorkerContext(),
       service_worker_handle_.get(), std::move(blob_url_loader_factory), nullptr,
@@ -346,34 +366,63 @@
     return;
   }
 
-  // TODO(https://crbug.com/1282637): Compute the client security state based on
-  // the response head and the creator's client security state, just like is
-  // currently done for COEP. Preserve existing functionality in the meantime.
-  worker_client_security_state_ =
-      ancestor_render_frame_host->BuildClientSecurityState();
-
-  // Alias the COEP field inside `worker_client_security_state_` for brevity
-  // below. Note that this is a reference, not a copy.
-  network::CrossOriginEmbedderPolicy& coep =
-      worker_client_security_state_->cross_origin_embedder_policy;
-
   // https://html.spec.whatwg.org/C/#run-a-worker
   if (final_response_url.SchemeIsBlob() ||
       final_response_url.SchemeIs(url::kAboutScheme) ||
-      final_response_url.SchemeIs(url::kDataScheme)) {
-    // > 14.5 If response's url's scheme is a local scheme, then set worker
-    // global scope's embedder policy to owner's embedder policy.
-    coep = creator_client_security_state_->cross_origin_embedder_policy;
-  } else if (main_script_load_params->response_head->parsed_headers) {
+      final_response_url.SchemeIs(url::kDataScheme) ||
+      // TODO(https://crbug.com/1146362): Inherit from the file creator instead
+      // once creator policies are persisted through the filesystem store.
+      final_response_url.SchemeIs(url::kFileSystemScheme)) {
+    if (base::FeatureList::IsEnabled(
+            features::kPrivateNetworkAccessForWorkers)) {
+      worker_client_security_state_ = creator_client_security_state_->Clone();
+    } else {
+      // Preserve incorrect functionality if PNA is not enabled.
+      worker_client_security_state_ =
+          ancestor_render_frame_host->BuildClientSecurityState();
+
+      // > 14.5 If response's url's scheme is a local scheme, then set worker
+      // global scope's embedder policy to owner's embedder policy.
+      worker_client_security_state_->cross_origin_embedder_policy =
+          creator_client_security_state_->cross_origin_embedder_policy;
+    }
+  } else if (main_script_load_params) {
+    DCHECK(main_script_load_params->response_head);
+    DCHECK(main_script_load_params->response_head->parsed_headers);
+
+    if (base::FeatureList::IsEnabled(
+            features::kPrivateNetworkAccessForWorkers)) {
+      worker_client_security_state_ =
+          network::mojom::ClientSecurityState::New();
+      worker_client_security_state_->ip_address_space = CalculateIPAddressSpace(
+          final_response_url, main_script_load_params->response_head.get(),
+          GetContentClient()->browser());
+      worker_client_security_state_->is_web_secure_context =
+          network::IsUrlPotentiallyTrustworthy(final_response_url) &&
+          creator_client_security_state_->is_web_secure_context;
+      worker_client_security_state_->private_network_request_policy =
+          DerivePrivateNetworkRequestPolicy(
+              worker_client_security_state_->ip_address_space,
+              worker_client_security_state_->is_web_secure_context);
+    } else {
+      // Preserve incorrect functionality if PNA is not enabled.
+      worker_client_security_state_ =
+          ancestor_render_frame_host->BuildClientSecurityState();
+    }
+
     // > 14.6 Otherwise, set worker global scope's embedder policy to the result
     // of obtaining an embedder policy from response.
-    coep = main_script_load_params->response_head->parsed_headers
-               ->cross_origin_embedder_policy;
+    worker_client_security_state_->cross_origin_embedder_policy =
+        main_script_load_params->response_head->parsed_headers
+            ->cross_origin_embedder_policy;
   }
 
   auto* storage_partition = static_cast<StoragePartitionImpl*>(
       worker_process_host_->GetStoragePartition());
+
   // Create a COEP reporter with worker's policy.
+  const network::CrossOriginEmbedderPolicy& coep =
+      worker_client_security_state_->cross_origin_embedder_policy;
   coep_reporter_ = std::make_unique<CrossOriginEmbedderPolicyReporter>(
       storage_partition->GetWeakPtr(), final_response_url,
       coep.reporting_endpoint, coep.report_only_reporting_endpoint,
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h
index be32e6b..f97b5d4 100644
--- a/content/browser/worker_host/dedicated_worker_host.h
+++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -173,6 +173,12 @@
     return reporting_source_;
   }
 
+  // Returns the client security state applied to subresource fetches.
+  // May return nullptr before the script is loaded.
+  const network::mojom::ClientSecurityState* client_security_state() const {
+    return worker_client_security_state_.get();
+  }
+
   const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy()
       const {
     DCHECK(worker_client_security_state_);
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 73a0dad5c0..5b87887 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -212,7 +212,10 @@
   worker_client_security_state_ = network::mojom::ClientSecurityState::New();
   if (final_response_url.SchemeIsBlob() ||
       final_response_url.SchemeIs(url::kAboutScheme) ||
-      final_response_url.SchemeIs(url::kDataScheme)) {
+      final_response_url.SchemeIs(url::kDataScheme) ||
+      // TODO(https://crbug.com/1146362): Inherit from the file creator instead
+      // once creator policies are persisted through the filesystem store.
+      final_response_url.SchemeIs(url::kFileSystemScheme)) {
     // > 13.6 If response's url's scheme is a local scheme, then set worker
     // global scope's embedder policy to owner's embedder policy.
     if (base::FeatureList::IsEnabled(
@@ -237,38 +240,37 @@
               worker_client_security_state_->ip_address_space,
               worker_client_security_state_->is_web_secure_context);
     }
-      // https://html.spec.whatwg.org/C/#run-a-worker
-      if (main_script_load_params->response_head->parsed_headers) {
-        // > 13.7 Otherwise, set worker global scope's embedder policy to the
-        // result of obtaining an embedder policy from response.
-        worker_client_security_state_->cross_origin_embedder_policy =
-            main_script_load_params->response_head->parsed_headers
-                ->cross_origin_embedder_policy;
-      }
-      switch (
-          worker_client_security_state_->cross_origin_embedder_policy.value) {
-        case network::mojom::CrossOriginEmbedderPolicyValue::kNone:
-          OnFeatureUsed(blink::mojom::WebFeature::kCoepNoneSharedWorker);
-          break;
-        case network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless:
-          OnFeatureUsed(
-              blink::mojom::WebFeature::kCoepCredentiallessSharedWorker);
-          break;
-        case network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp:
-          OnFeatureUsed(blink::mojom::WebFeature::kCoepRequireCorpSharedWorker);
-          break;
-      }
+    // https://html.spec.whatwg.org/C/#run-a-worker
+    if (main_script_load_params->response_head->parsed_headers) {
+      // > 13.7 Otherwise, set worker global scope's embedder policy to the
+      // result of obtaining an embedder policy from response.
+      worker_client_security_state_->cross_origin_embedder_policy =
+          main_script_load_params->response_head->parsed_headers
+              ->cross_origin_embedder_policy;
+    }
+    switch (worker_client_security_state_->cross_origin_embedder_policy.value) {
+      case network::mojom::CrossOriginEmbedderPolicyValue::kNone:
+        OnFeatureUsed(blink::mojom::WebFeature::kCoepNoneSharedWorker);
+        break;
+      case network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless:
+        OnFeatureUsed(
+            blink::mojom::WebFeature::kCoepCredentiallessSharedWorker);
+        break;
+      case network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp:
+        OnFeatureUsed(blink::mojom::WebFeature::kCoepRequireCorpSharedWorker);
+        break;
+    }
 
-      auto* storage_partition = static_cast<StoragePartitionImpl*>(
-          GetProcessHost()->GetStoragePartition());
-      // Create a COEP reporter with worker's policy.
-      coep_reporter_ = std::make_unique<CrossOriginEmbedderPolicyReporter>(
-          storage_partition->GetWeakPtr(), final_response_url,
-          worker_client_security_state_->cross_origin_embedder_policy
-              .reporting_endpoint,
-          worker_client_security_state_->cross_origin_embedder_policy
-              .report_only_reporting_endpoint,
-          GetReportingSource(), GetNetworkIsolationKey());
+    auto* storage_partition = static_cast<StoragePartitionImpl*>(
+        GetProcessHost()->GetStoragePartition());
+    // Create a COEP reporter with worker's policy.
+    coep_reporter_ = std::make_unique<CrossOriginEmbedderPolicyReporter>(
+        storage_partition->GetWeakPtr(), final_response_url,
+        worker_client_security_state_->cross_origin_embedder_policy
+            .reporting_endpoint,
+        worker_client_security_state_->cross_origin_embedder_policy
+            .report_only_reporting_endpoint,
+        GetReportingSource(), GetNetworkIsolationKey());
   }
 
   auto options = blink::mojom::WorkerOptions::New(
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 3c92583..eb2f65c 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -364,7 +364,8 @@
           host->instance().storage_key().nonce().has_value()
               ? &host->instance().storage_key().nonce().value()
               : nullptr),
-      credentials_mode, std::move(outside_fetch_client_settings_object),
+      creator.BuildClientSecurityState(), credentials_mode,
+      std::move(outside_fetch_client_settings_object),
       network::mojom::RequestDestination::kSharedWorker,
       service_worker_context_, service_worker_handle_raw,
       std::move(blob_url_loader_factory), url_loader_factory_override_,
diff --git a/content/browser/worker_host/worker_script_fetcher.cc b/content/browser/worker_host/worker_script_fetcher.cc
index 5cb3e11..f2322f1 100644
--- a/content/browser/worker_host/worker_script_fetcher.cc
+++ b/content/browser/worker_host/worker_script_fetcher.cc
@@ -44,6 +44,7 @@
 #include "services/network/public/cpp/constants.h"
 #include "services/network/public/cpp/ip_address_space_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/client_security_state.mojom.h"
 #include "services/network/public/mojom/early_hints.mojom.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
@@ -208,6 +209,7 @@
     const url::Origin& request_initiator,
     const blink::StorageKey& request_initiator_storage_key,
     const net::IsolationInfo& trusted_isolation_info,
+    network::mojom::ClientSecurityStatePtr client_security_state,
     network::mojom::CredentialsMode credentials_mode,
     blink::mojom::FetchClientSettingsObjectPtr
         outside_fetch_client_settings_object,
@@ -223,6 +225,7 @@
     const base::UnguessableToken& devtools_worker_token,
     CompletionCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(client_security_state);
   DCHECK(storage_partition);
   DCHECK(devtools_agent_host);
   DCHECK(request_destination == network::mojom::RequestDestination::kWorker ||
@@ -326,8 +329,8 @@
   WorkerScriptFetcher::CreateScriptLoader(
       worker_process_id, worker_token, initial_request_url,
       ancestor_render_frame_host, creator_render_frame_host,
-      trusted_isolation_info, std::move(resource_request),
-      std::move(factory_bundle_for_browser),
+      trusted_isolation_info, std::move(client_security_state),
+      std::move(resource_request), std::move(factory_bundle_for_browser),
       std::move(subresource_loader_factories),
       std::move(service_worker_context), service_worker_handle,
       std::move(blob_url_loader_factory),
@@ -342,6 +345,7 @@
     RenderFrameHostImpl* ancestor_render_frame_host,
     RenderFrameHostImpl* creator_render_frame_host,
     const net::IsolationInfo& trusted_isolation_info,
+    network::mojom::ClientSecurityStatePtr client_security_state,
     std::unique_ptr<network::ResourceRequest> resource_request,
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
         factory_bundle_for_browser_info,
@@ -357,6 +361,7 @@
     WorkerScriptFetcher::CompletionCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(devtools_agent_host);
+  DCHECK(client_security_state);
 
   RenderProcessHost* factory_process =
       RenderProcessHost::FromID(worker_process_id);
@@ -365,15 +370,9 @@
   BrowserContext* browser_context = factory_process->GetBrowserContext();
   DCHECK(browser_context);  // Checked in the Start method.
 
-  network::mojom::ClientSecurityStatePtr client_security_state;
-  if (creator_render_frame_host) {
-    client_security_state =
-        creator_render_frame_host->BuildClientSecurityState();
-
-    // Do not enforce COEP on the main script fetch.
-    client_security_state->cross_origin_embedder_policy =
-        network::CrossOriginEmbedderPolicy();
-  }
+  // Do not enforce COEP on the main script fetch.
+  client_security_state->cross_origin_embedder_policy =
+      network::CrossOriginEmbedderPolicy();
 
   // Create the URL loader factory for WorkerScriptLoaderFactory to use to load
   // the main script.
diff --git a/content/browser/worker_host/worker_script_fetcher.h b/content/browser/worker_host/worker_script_fetcher.h
index 0366da9..30f73a4 100644
--- a/content/browser/worker_host/worker_script_fetcher.h
+++ b/content/browser/worker_host/worker_script_fetcher.h
@@ -13,6 +13,7 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/client_security_state.mojom-forward.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -64,7 +65,8 @@
   // Called with the result of fetching a script upon completion.
   //
   // - `subresource_loader_factories` is never nullptr.
-  // - `main_script_load_params` is nullptr iff the fetch failed.
+  // - `main_script_load_params` is nullptr iff the fetch failed. Otherwise, it
+  //    always contains `response_head` and `response_head->parsed_headers`.
   // - `controller` and `controller_service_worker_object_host` may be nullptr.
   // - `final_response_url` specifies the script response URL.
   using CompletionCallback = base::OnceCallback<void(
@@ -98,6 +100,9 @@
   //   Since nested shared workers are not supported, for shared workers
   //   `ancestor_render_frame_host` and `creator_render_frame_host` are always
   //   equal.
+  // - `client_security_state` specifies parameters to be passed to the network
+  //   service `URLLoaderFactory`, for use when loading the script. It must not
+  //   be nullptr.
   // - `callback` will be called with the result on the UI thread.
   static void CreateAndStart(
       int worker_process_id,
@@ -109,6 +114,7 @@
       const url::Origin& request_initiator,
       const blink::StorageKey& request_initiator_storage_key,
       const net::IsolationInfo& trusted_isolation_info,
+      network::mojom::ClientSecurityStatePtr client_security_state,
       network::mojom::CredentialsMode credentials_mode,
       blink::mojom::FetchClientSettingsObjectPtr
           outside_fetch_client_settings_object,
@@ -180,6 +186,7 @@
       RenderFrameHostImpl* ancestor_render_frame_host,
       RenderFrameHostImpl* creator_render_frame_host,
       const net::IsolationInfo& trusted_isolation_info,
+      network::mojom::ClientSecurityStatePtr client_security_state,
       std::unique_ptr<network::ResourceRequest> resource_request,
       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
           factory_bundle_for_browser_info,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 292cfdf..5a4aac8 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -196,8 +196,6 @@
       blinkFeatureToBaseFeatureMapping[] =
   { {wf::EnableAccessibilityAriaVirtualContent,
      features::kEnableAccessibilityAriaVirtualContent},
-    {wf::EnableAccessibilityExposeDisplayNone,
-     features::kEnableAccessibilityExposeDisplayNone},
     {wf::EnableAccessibilityExposeHTMLElement,
      features::kEnableAccessibilityExposeHTMLElement},
     {wf::EnableAccessibilityExposeIgnoredNodes,
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 1b21d52..25f5f67a 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -1342,11 +1342,16 @@
   // destruction. If the prerendering failed to start (e.g. if prerendering is
   // disabled, failure happened or because this URL is already being
   // prerendered), this function returns a nullptr.
+  // `url_match_predicate` allows embedders to define their own pedicates for
+  // matching sane-origin URLs during prerendering activation; It would be
+  // useful if embedders want Prerender2 to ignore some parameter mismatches.
   virtual std::unique_ptr<PrerenderHandle> StartPrerendering(
       const GURL& prerendering_url,
       PrerenderTriggerType trigger_type,
       const std::string& embedder_histogram_suffix,
-      ui::PageTransition page_transition) = 0;
+      ui::PageTransition page_transition,
+      absl::optional<base::RepeatingCallback<bool(const GURL&)>>
+          url_match_predicate = absl::nullopt) = 0;
 
  private:
   // This interface should only be implemented inside content.
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index fe649cc..292ec4e 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -421,7 +421,8 @@
                           rfhi->GetLastCommittedOrigin(),
                           rfhi->GetLastCommittedURL(),
                           rfhi->GetProcess()->GetID(), rfhi->GetFrameToken(),
-                          rfhi->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK),
+                          rfhi->GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK,
+                          /*url_match_predicate=*/absl::nullopt),
       *this);
 }
 
diff --git a/infra/config/generated/builders/ci/android-bfcache-rel/properties.textpb b/infra/config/generated/builders/ci/android-no-bfcache-rel/properties.textpb
similarity index 100%
rename from infra/config/generated/builders/ci/android-bfcache-rel/properties.textpb
rename to infra/config/generated/builders/ci/android-no-bfcache-rel/properties.textpb
diff --git a/infra/config/generated/builders/ci/linux-bfcache-rel/properties.textpb b/infra/config/generated/builders/ci/linux-no-bfcache-rel/properties.textpb
similarity index 100%
rename from infra/config/generated/builders/ci/linux-bfcache-rel/properties.textpb
rename to infra/config/generated/builders/ci/linux-no-bfcache-rel/properties.textpb
diff --git a/infra/config/generated/builders/try/android-bfcache-rel/properties.textpb b/infra/config/generated/builders/try/android-no-bfcache-rel/properties.textpb
similarity index 100%
rename from infra/config/generated/builders/try/android-bfcache-rel/properties.textpb
rename to infra/config/generated/builders/try/android-no-bfcache-rel/properties.textpb
diff --git a/infra/config/generated/builders/try/linux-bfcache-rel/properties.textpb b/infra/config/generated/builders/try/linux-no-bfcache-rel/properties.textpb
similarity index 100%
rename from infra/config/generated/builders/try/linux-bfcache-rel/properties.textpb
rename to infra/config/generated/builders/try/linux-no-bfcache-rel/properties.textpb
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 12177a5a..397c9e2 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -297,10 +297,6 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/android-bfcache-rel"
-        includable_only: true
-      }
-      builders {
         name: "chromium/try/android-binary-size"
         location_regexp: ".*"
         location_regexp_exclude: ".+/[+]/docs/.+"
@@ -419,6 +415,10 @@
         location_regexp_exclude: ".+/[+]/infra/config/.+"
       }
       builders {
+        name: "chromium/try/android-no-bfcache-rel"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/android-official"
         includable_only: true
       }
@@ -1212,10 +1212,6 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/linux-bfcache-rel"
-        includable_only: true
-      }
-      builders {
         name: "chromium/try/linux-bionic-rel"
         includable_only: true
       }
@@ -1379,6 +1375,10 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/linux-no-bfcache-rel"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/linux-official"
         includable_only: true
       }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index adacab40..38f87fa 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -24908,92 +24908,6 @@
       }
     }
     builders {
-      name: "android-bfcache-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.ci"
-      dimensions: "ssd:0"
-      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/android-bfcache-rel/properties.textpb",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.android",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium",'
-        '  "sheriff_rotations": ['
-        '    "android"'
-        '  ]'
-        '}'
-      execution_timeout_secs: 10800
-      build_numbers: YES
-      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        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/.+"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-    }
-    builders {
       name: "android-binary-size-generator"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:android-binary-size-generator"
@@ -26947,6 +26861,92 @@
       }
     }
     builders {
+      name: "android-no-bfcache-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      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/android-no-bfcache-rel/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium",'
+        '  "sheriff_rotations": ['
+        '    "android"'
+        '  ]'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        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/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "android-official"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:android-official"
@@ -33915,92 +33915,6 @@
       }
     }
     builders {
-      name: "linux-bfcache-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.ci"
-      dimensions: "ssd:0"
-      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/linux-bfcache-rel/properties.textpb",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.linux",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium",'
-        '  "sheriff_rotations": ['
-        '    "chromium"'
-        '  ]'
-        '}'
-      execution_timeout_secs: 10800
-      build_numbers: YES
-      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        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/.+"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-    }
-    builders {
       name: "linux-bionic-rel"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -36355,6 +36269,92 @@
       }
     }
     builders {
+      name: "linux-no-bfcache-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      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/linux-no-bfcache-rel/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium",'
+        '  "sheriff_rotations": ['
+        '    "chromium"'
+        '  ]'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        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/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-official"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:linux-official"
@@ -49185,100 +49185,6 @@
       }
     }
     builders {
-      name: "android-bfcache-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.try"
-      dimensions: "ssd:0"
-      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/try/android-bfcache-rel/properties.textpb",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.chromium.android",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium_trybot"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_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_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-    }
-    builders {
       name: "android-binary-size"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:android-binary-size"
@@ -51625,6 +51531,100 @@
       }
     }
     builders {
+      name: "android-no-bfcache-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      dimensions: "ssd:0"
+      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/try/android-no-bfcache-rel/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_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_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "android-official"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -66199,100 +66199,6 @@
       }
     }
     builders {
-      name: "linux-bfcache-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.try"
-      dimensions: "ssd:0"
-      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/try/linux-bfcache-rel/properties.textpb",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.chromium.linux",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium_trybot"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_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_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-    }
-    builders {
       name: "linux-bionic-rel"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
@@ -69467,6 +69373,100 @@
       }
     }
     builders {
+      name: "linux-no-bfcache-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try"
+      dimensions: "ssd:0"
+      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/try/linux-no-bfcache-rel/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium_trybot"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_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_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-official"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 0d9a106..d7fb5f4 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -341,7 +341,7 @@
     short_name: "64"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/linux-bfcache-rel"
+    name: "buildbucket/luci.chromium.ci/linux-no-bfcache-rel"
     category: "chromium.linux|bfcache"
     short_name: "bfc"
   }
@@ -3261,7 +3261,7 @@
     short_name: "P"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/android-bfcache-rel"
+    name: "buildbucket/luci.chromium.ci/android-no-bfcache-rel"
     category: "bfcache"
     short_name: "bfc"
   }
@@ -8795,7 +8795,7 @@
     short_name: "64"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/linux-bfcache-rel"
+    name: "buildbucket/luci.chromium.ci/linux-no-bfcache-rel"
     category: "bfcache"
     short_name: "bfc"
   }
@@ -14105,9 +14105,6 @@
     name: "buildbucket/luci.chromium.try/android-asan"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-bfcache-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android-binary-size"
   }
   builders {
@@ -14183,6 +14180,9 @@
     name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-rts"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-no-bfcache-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-official"
   }
   builders {
@@ -14657,9 +14657,6 @@
     name: "buildbucket/luci.chromium.try/linux-autofill-assistant"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-bfcache-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux-bionic-rel"
   }
   builders {
@@ -14762,6 +14759,9 @@
     name: "buildbucket/luci.chromium.try/linux-mbi-mode-per-site-instance-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/linux-no-bfcache-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/linux-official"
   }
   builders {
@@ -15231,9 +15231,6 @@
     name: "buildbucket/luci.chromium.try/android-asan"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-bfcache-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android-binary-size"
   }
   builders {
@@ -15309,6 +15306,9 @@
     name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-rts"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-no-bfcache-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-opus-arm-rel"
   }
   builders {
@@ -15751,9 +15751,6 @@
     name: "buildbucket/luci.chromium.try/linux-autofill-assistant"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-bfcache-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux-bionic-rel"
   }
   builders {
@@ -15811,6 +15808,9 @@
     name: "buildbucket/luci.chromium.try/linux-mbi-mode-per-site-instance-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/linux-no-bfcache-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/linux-perfetto-rel"
   }
   builders {
diff --git a/infra/config/generated/luci/luci-notify.cfg b/infra/config/generated/luci/luci-notify.cfg
index c33c58b..9335eb0 100644
--- a/infra/config/generated/luci/luci-notify.cfg
+++ b/infra/config/generated/luci/luci-notify.cfg
@@ -3159,32 +3159,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-    template: "tree_closure_email_template"
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
-    email {
-      recipients: "thomasanderson@chromium.org"
-    }
-  }
-  builders {
-    bucket: "ci"
-    name: "linux-bfcache-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3401,6 +3375,32 @@
 }
 notifiers {
   notifications {
+    on_occurrence: FAILURE
+    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
+    email {
+      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
+    }
+    template: "tree_closure_email_template"
+  }
+  notifications {
+    on_occurrence: FAILURE
+    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
+    email {
+      recipients: "thomasanderson@chromium.org"
+    }
+  }
+  builders {
+    bucket: "ci"
+    name: "linux-no-bfcache-rel"
+    repository: "https://chromium.googlesource.com/chromium/src"
+  }
+  tree_closers {
+    tree_status_host: "chromium-status.appspot.com"
+    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
+  }
+}
+notifiers {
+  notifications {
     on_change: true
     email {
       recipients: "chrome-memory-safety+bots@google.com"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 7ed6069..7a995d3 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4221,16 +4221,6 @@
   }
 }
 job {
-  id: "android-bfcache-rel"
-  realm: "ci"
-  acl_sets: "ci"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "ci"
-    builder: "android-bfcache-rel"
-  }
-}
-job {
   id: "android-binary-size-generator"
   realm: "ci"
   acl_sets: "ci"
@@ -4490,6 +4480,16 @@
   }
 }
 job {
+  id: "android-no-bfcache-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "android-no-bfcache-rel"
+  }
+}
+job {
   id: "android-official"
   realm: "ci"
   acl_sets: "ci"
@@ -4998,7 +4998,7 @@
   acl_sets: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
+    bucket: "ci"
     builder: "gpu-fyi-chromeos-jacuzzi-exp"
   }
 }
@@ -5458,16 +5458,6 @@
   }
 }
 job {
-  id: "linux-bfcache-rel"
-  realm: "ci"
-  acl_sets: "ci"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "ci"
-    builder: "linux-bfcache-rel"
-  }
-}
-job {
   id: "linux-bionic-rel"
   realm: "ci"
   acl_sets: "ci"
@@ -5753,6 +5743,16 @@
   }
 }
 job {
+  id: "linux-no-bfcache-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "linux-no-bfcache-rel"
+  }
+}
+job {
   id: "linux-official"
   realm: "ci"
   acl_sets: "ci"
@@ -7109,7 +7109,6 @@
   triggers: "android-asan"
   triggers: "android-backuprefptr-arm-fyi-rel"
   triggers: "android-backuprefptr-arm64-fyi-rel"
-  triggers: "android-bfcache-rel"
   triggers: "android-binary-size-generator"
   triggers: "android-chrome-pie-x86-wpt-fyi-rel"
   triggers: "android-code-coverage-native"
@@ -7125,6 +7124,7 @@
   triggers: "android-marshmallow-arm64-rel"
   triggers: "android-marshmallow-x86-rel"
   triggers: "android-marshmallow-x86-rel-non-cq"
+  triggers: "android-no-bfcache-rel"
   triggers: "android-official"
   triggers: "android-pie-arm64-coverage-experimental-rel"
   triggers: "android-pie-arm64-rel"
@@ -7189,7 +7189,6 @@
   triggers: "linux-archive-rel"
   triggers: "linux-ash-chromium-builder-fyi-rel"
   triggers: "linux-backuprefptr-x64-fyi-rel"
-  triggers: "linux-bfcache-rel"
   triggers: "linux-bionic-rel"
   triggers: "linux-blink-animation-use-time-delta"
   triggers: "linux-blink-heap-concurrent-marking-tsan-rel"
@@ -7211,6 +7210,7 @@
   triggers: "linux-lacros-dbg"
   triggers: "linux-lacros-dbg-fyi"
   triggers: "linux-lacros-version-skew-fyi"
+  triggers: "linux-no-bfcache-rel"
   triggers: "linux-official"
   triggers: "linux-perfetto-rel"
   triggers: "linux-rust-x64-rel"
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star
index 5865353..6a2fb17 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -259,7 +259,7 @@
 )
 
 ci.builder(
-    name = "android-bfcache-rel",
+    name = "android-no-bfcache-rel",
     console_view_entry = consoles.console_view_entry(
         category = "bfcache",
         short_name = "bfc",
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star
index 514b0ec..e6c21ee 100644
--- a/infra/config/subprojects/chromium/ci/chromium.linux.star
+++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -357,7 +357,7 @@
 )
 
 ci.builder(
-    name = "linux-bfcache-rel",
+    name = "linux-no-bfcache-rel",
     console_view_entry = consoles.console_view_entry(
         category = "bfcache",
         short_name = "bfc",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index 6a0f7de10e..6768d57 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -60,7 +60,7 @@
 )
 
 try_.builder(
-    name = "android-bfcache-rel",
+    name = "android-no-bfcache-rel",
 )
 
 try_.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index 1ba7d8da..2468f968 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -185,7 +185,7 @@
 )
 
 try_.builder(
-    name = "linux-bfcache-rel",
+    name = "linux-no-bfcache-rel",
 )
 
 try_.builder(
diff --git a/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm
index 2f5b438..704a3b2a 100644
--- a/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm
@@ -15,20 +15,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// Reuse ID for registering cell class in table views.
-constexpr NSString* kReuseID = @"InstructionTableCell";
-
-}  // namespace
-
-@interface DefaultBrowserScreenViewController ()
-
-// Instruction list to set the default browser.
-@property(nonatomic, strong) NSArray* defaultBrowserSteps;
-
-@end
-
 @implementation DefaultBrowserScreenViewController
 
 #pragma mark - UIViewController
@@ -48,7 +34,7 @@
   self.secondaryActionString = l10n_util::GetNSString(
       IDS_IOS_FIRST_RUN_DEFAULT_BROWSER_SCREEN_SECONDARY_ACTION);
 
-  self.defaultBrowserSteps = @[
+  NSArray* defaultBrowserSteps = @[
     l10n_util::GetNSString(IDS_IOS_FIRST_RUN_DEFAULT_BROWSER_SCREEN_FIRST_STEP),
     l10n_util::GetNSString(
         IDS_IOS_FIRST_RUN_DEFAULT_BROWSER_SCREEN_SECOND_STEP),
@@ -56,7 +42,7 @@
   ];
 
   UIView* instructionView =
-      [[InstructionView alloc] initWithList:self.defaultBrowserSteps];
+      [[InstructionView alloc] initWithList:defaultBrowserSteps];
   instructionView.translatesAutoresizingMaskIntoConstraints = NO;
 
   [self.specificContentView addSubview:instructionView];
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm
index 063e3b7..feb4b13 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_egtest.mm
@@ -174,11 +174,16 @@
 // Navigates to a pdf page and verifies that the "Find in Page..." tool
 // is not enabled
 - (void)testNoSearchForPDF {
-// TODO(crbug.com/1209346): test failing on ipad device
 #if !TARGET_IPHONE_SIMULATOR
+  // TODO(crbug.com/1209346): test failing on ipad device
   if ([ChromeEarlGrey isIPadIdiom]) {
     EARL_GREY_TEST_SKIPPED(@"This test doesn't pass on iPad device.");
   }
+#else
+  // TODO(crbug.com/1293132): Test is flaky on iphone simulator.
+  if (![ChromeEarlGrey isIPadIdiom]) {
+    EARL_GREY_TEST_SKIPPED(@"This test is flaky on iPhone simulator.");
+  }
 #endif
   const GURL URL = web::test::HttpServer::MakeUrl(kPDFURL);
 
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 0da4d8b..26fcb58 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-96b42d045a7429f8902466eef511b32a8b8179a0
\ No newline at end of file
+2b32fe92f8bb0c71d103f80691eae45cf34d95bc
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 04ace19..54631fd 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-f64b900299ae55ddfec328b999f255b45c8e74af
\ No newline at end of file
+6d4b62b7f72c3171de069569f3bfb003b262d564
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 3b38546..abceb86 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-fbea47723c89cc16cab5de7a24835ad65a4b2ddb
\ No newline at end of file
+c0849d64e03e04749695196f65e8c8eb53654de1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 49212e0..ec05d42 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-12fa3d3964afcd3e6d8d15cf80be8420bed11a70
\ No newline at end of file
+4f329587e6c4da681880ecb3dc1bf36266225fbf
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 131a2b81..29c294c2 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ed019da919dad42380383c36b602b935a144da7e
\ No newline at end of file
+6b04c3df9e4e72159401508a93f0309033da7da7
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 0a6e4e4..c6ebb1e8 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-f878115eea22b0066b35ffae50c62fccc3d2fe98
\ No newline at end of file
+e8f9fae1b6c0f60fe8bbc8c1aec57049b0dfc5a0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 2015c90..0a0bd952 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ae097b1af47bfc8f326234c27f4d964ac55eecd0
\ No newline at end of file
+ab81bc05f4477bfb1d9e30d199068ad31fbeac70
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 77eadb2..7b284e3 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-3ebc360c16d91d327fe952f9c031f95fe28e95dd
\ No newline at end of file
+8f6a4009431e5483c33015cec51047dd2a27f51a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 00eff7a..1e4454e 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-05c27064883fc2219a02770ddc5912feebae9aa1
\ No newline at end of file
+5a8e2791c402ecf38a297c615a60a29999d38daf
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index c31d2a7..76d958a1 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-2d5f27f02fe2487f3d40dab9dd3bb10996d64ba3
\ No newline at end of file
+aaeec9f5870eec34a87135e3f3adfe969ee4c812
\ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
index d3b97f2..761ff6c 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -234,6 +234,11 @@
   void CanOfferExtendedSyncPromos(ChromeIdentity* identity,
                                   CapabilitiesCallback callback);
 
+  // Asynchronously returns the value of the account capability that determines
+  // whether parental controls should be applied to |identity|.
+  void IsSubjectToParentalControls(ChromeIdentity* identity,
+                                   CapabilitiesCallback callback);
+
   // Returns true if the service can be used, and supports ChromeIdentity list.
   virtual bool IsServiceSupported();
 
@@ -282,6 +287,11 @@
   void FireProfileDidUpdate(ChromeIdentity* identity);
 
  private:
+  // Asynchronously retrieves the specified capability for the Chrome identity.
+  void FetchCapability(ChromeIdentity* identity,
+                       NSString* capability_name,
+                       CapabilitiesCallback completion);
+
   base::ObserverList<Observer, true>::Unchecked observer_list_;
 };
 
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
index 444c56f..834f789 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -149,26 +149,15 @@
 void ChromeIdentityService::CanOfferExtendedSyncPromos(
     ChromeIdentity* identity,
     CapabilitiesCallback completion) {
-  NSString* canOfferExtendedChromeSyncPromos = [NSString
-      stringWithUTF8String:kCanOfferExtendedChromeSyncPromosCapabilityName];
-  base::TimeTicks fetch_start = base::TimeTicks::Now();
-  FetchCapabilities(
-      @[ canOfferExtendedChromeSyncPromos ], identity,
-      ^(NSDictionary<NSString*, NSNumber*>* capabilities, NSError* error) {
-        base::UmaHistogramTimes(
-            "Signin.AccountCapabilities.GetFromSystemLibraryDuration",
-            base::TimeTicks::Now() - fetch_start);
+  FetchCapability(identity, @(kCanOfferExtendedChromeSyncPromosCapabilityName),
+                  completion);
+}
 
-        FetchCapabilitiesResult result = ComputeFetchCapabilitiesResult(
-            [capabilities objectForKey:canOfferExtendedChromeSyncPromos],
-            error);
-        base::UmaHistogramEnumeration(
-            "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-            result.fetch_result);
-
-        if (completion)
-          completion(result.capability_value);
-      });
+void ChromeIdentityService::IsSubjectToParentalControls(
+    ChromeIdentity* identity,
+    CapabilitiesCallback completion) {
+  FetchCapability(identity, @(kIsSubjectToParentalControlsCapabilityName),
+                  completion);
 }
 
 bool ChromeIdentityService::IsServiceSupported() {
@@ -227,4 +216,26 @@
     observer.OnProfileUpdate(identity);
 }
 
+void ChromeIdentityService::FetchCapability(ChromeIdentity* identity,
+                                            NSString* capability_name,
+                                            CapabilitiesCallback completion) {
+  base::TimeTicks fetch_start = base::TimeTicks::Now();
+  FetchCapabilities(
+      @[ capability_name ], identity,
+      ^(NSDictionary<NSString*, NSNumber*>* capabilities, NSError* error) {
+        base::UmaHistogramTimes(
+            "Signin.AccountCapabilities.GetFromSystemLibraryDuration",
+            base::TimeTicks::Now() - fetch_start);
+
+        FetchCapabilitiesResult result = ComputeFetchCapabilitiesResult(
+            [capabilities objectForKey:capability_name], error);
+        base::UmaHistogramEnumeration(
+            "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+            result.fetch_result);
+
+        if (completion)
+          completion(result.capability_value);
+      });
+}
+
 }  // namespace ios
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service_unittest.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service_unittest.mm
index 360739a8..5a34717 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service_unittest.mm
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service_unittest.mm
@@ -24,6 +24,10 @@
 namespace ios {
 namespace {
 
+// A wrapper for the API to fetch Capability results for a specific Capability
+// type.
+using CapabilityFetcherBlock = void (^)(ChromeIdentityCapabilityResult*);
+
 class TestChromeIdentityService : public ChromeIdentityService {
  public:
   struct FetchCapabilitiesRequest {
@@ -35,16 +39,31 @@
   TestChromeIdentityService() = default;
   ~TestChromeIdentityService() override = default;
 
-  const FetchCapabilitiesRequest& fetch_capabilities_request() const {
-    return fetch_capabilities_request_.value();
+  // Sets the capability and its corresponding fetcher in the test service.
+  void SetCapabilityUnderTest(NSString* capability_name,
+                              CapabilityFetcherBlock capability_fetcher_block) {
+    capability_name_ = capability_name;
+    capability_fetcher_block_ = capability_fetcher_block;
   }
 
-  void RunFinishCapabilitiesCompletion(NSDictionary* capabilities,
-                                       NSError* error) {
-    EXPECT_TRUE(fetch_capabilities_request_.has_value());
-    EXPECT_TRUE(fetch_capabilities_request_.value().completion);
-    fetch_capabilities_request_.value().completion(capabilities, error);
-    fetch_capabilities_request_.reset();
+  // Retrieves the capability tribool result for the capability under test.
+  ChromeIdentityCapabilityResult FetchCapability(NSNumber* capability_value,
+                                                 NSError* error) {
+    base::HistogramTester histogramTester;
+    base::ScopedMockClockOverride clock;
+    ChromeIdentityCapabilityResult result;
+    capability_fetcher_block_(&result);
+
+    clock.Advance(base::Minutes(1));
+    // Capability result is set after completion.
+    RunFinishCapabilitiesCompletion(capability_value, error);
+
+    histogramTester.ExpectUniqueTimeSample(
+        "Signin.AccountCapabilities.GetFromSystemLibraryDuration",
+        base::Minutes(1),
+        /*expected_bucket_count=*/1);
+
+    return result;
   }
 
  protected:
@@ -61,7 +80,19 @@
   }
 
  private:
+  void RunFinishCapabilitiesCompletion(NSNumber* capability_value,
+                                       NSError* error) {
+    NSDictionary* capabilities =
+        capability_value ? @{capability_name_ : capability_value} : nil;
+    EXPECT_TRUE(fetch_capabilities_request_.has_value());
+    EXPECT_TRUE(fetch_capabilities_request_.value().completion);
+    fetch_capabilities_request_.value().completion(capabilities, error);
+    fetch_capabilities_request_.reset();
+  }
+
   absl::optional<FetchCapabilitiesRequest> fetch_capabilities_request_;
+  NSString* capability_name_ = nil;
+  CapabilityFetcherBlock capability_fetcher_block_ = nil;
 };
 
 class ChromeIdentityServiceTest : public PlatformTest {
@@ -74,130 +105,120 @@
   ~ChromeIdentityServiceTest() override = default;
 
  protected:
-  ChromeIdentityCapabilityResult FetchCanOfferExtendedSyncPromos(
-      ChromeIdentity* identity,
-      int capability_value) {
-    base::HistogramTester histogramTester;
-    ChromeIdentityCapabilityResult result = FetchCanOfferExtendedSyncPromos(
-        identity, [NSNumber numberWithInt:capability_value], /*error=*/nil);
-    histogramTester.ExpectUniqueSample(
-        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-        FetchAccountCapabilitiesFromSystemLibraryResult::kSuccess, 1);
-    return result;
-  }
-
-  ChromeIdentityCapabilityResult FetchCanOfferExtendedSyncPromos(
-      ChromeIdentity* identity,
-      NSNumber* capability_value,
-      NSError* error) {
-    __block ChromeIdentityCapabilityResult fetched_capability_result;
-    service_.CanOfferExtendedSyncPromos(
-        identity, ^(ChromeIdentityCapabilityResult result) {
-          fetched_capability_result = result;
-        });
-    EXPECT_NSEQ(@[ @(kCanOfferExtendedChromeSyncPromosCapabilityName) ],
-                service_.fetch_capabilities_request().capabilities);
-    EXPECT_EQ(identity, service_.fetch_capabilities_request().identity);
-
-    NSDictionary* capability_values = capability_value ? @{
-      @(kCanOfferExtendedChromeSyncPromosCapabilityName) : capability_value
-    }
-                                                       : nil;
-    service_.RunFinishCapabilitiesCompletion(capability_values, error);
-    return fetched_capability_result;
+  void RunCapabilitySmokeTests() {
+    CheckChromeIdentityCapabilityResult();
+    CheckMissingCapability();
+    CheckCapabilityValueOutOfRange();
+    CheckCapabillityFetcherWithError();
   }
 
   FakeChromeIdentity* identity_;
   TestChromeIdentityService service_;
+
+ private:
+  void CheckChromeIdentityCapabilityResult() {
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kFalse,
+                service_.FetchCapability(/*capability_value=*/@0, nil));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kSuccess, 1);
+    }
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kTrue,
+                service_.FetchCapability(/*capability_value=*/@1, nil));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kSuccess, 1);
+    }
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+                service_.FetchCapability(/*capability_value=*/@2, nil));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kSuccess, 1);
+    }
+  }
+
+  void CheckMissingCapability() {
+    base::HistogramTester histogramTester;
+    EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+              service_.FetchCapability(/*capability_value=*/nil, nil));
+    histogramTester.ExpectUniqueSample(
+        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+        FetchAccountCapabilitiesFromSystemLibraryResult::
+            kErrorMissingCapability,
+        1);
+  }
+
+  void CheckCapabilityValueOutOfRange() {
+    base::HistogramTester histogramTester;
+    EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+              service_.FetchCapability(/*capability_value=*/@100, nil));
+    histogramTester.ExpectUniqueSample(
+        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+        FetchAccountCapabilitiesFromSystemLibraryResult::kErrorUnexpectedValue,
+        1);
+  }
+
+  void CheckCapabillityFetcherWithError() {
+    NSError* error = [NSError errorWithDomain:@"test" code:-100 userInfo:nil];
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+                service_.FetchCapability(
+                    /*capability_value=*/nil, error));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
+    }
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+                service_.FetchCapability(/*capability_value=*/@0, error));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
+    }
+    {
+      base::HistogramTester histogramTester;
+      EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
+                service_.FetchCapability(
+                    /*capability_value=*/@1, error));
+      histogramTester.ExpectUniqueSample(
+          "Signin.AccountCapabilities.GetFromSystemLibraryResult",
+          FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
+    }
+  }
 };
 
 TEST_F(ChromeIdentityServiceTest, CanOfferExtendedSyncPromos) {
-  EXPECT_EQ(ChromeIdentityCapabilityResult::kFalse,
-            FetchCanOfferExtendedSyncPromos(identity_,
-                                            /*capability_value=*/0));
+  service_.SetCapabilityUnderTest(
+      @(kCanOfferExtendedChromeSyncPromosCapabilityName),
+      ^(ChromeIdentityCapabilityResult* fetched_capability_result) {
+        service_.CanOfferExtendedSyncPromos(
+            identity_, ^(ChromeIdentityCapabilityResult result) {
+              *fetched_capability_result = result;
+            });
+      });
 
-  EXPECT_EQ(ChromeIdentityCapabilityResult::kTrue,
-            FetchCanOfferExtendedSyncPromos(identity_,
-                                            /*capability_value=*/1));
-
-  EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
-            FetchCanOfferExtendedSyncPromos(identity_,
-                                            /*capability_value=*/2));
+  RunCapabilitySmokeTests();
 }
 
-TEST_F(ChromeIdentityServiceTest,
-       CanOfferExtendedSyncPromos_MissingCapability) {
-  base::HistogramTester histogramTester;
-  EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
-            FetchCanOfferExtendedSyncPromos(identity_, /*capability_value=*/nil,
-                                            /*error=*/nil));
-  histogramTester.ExpectUniqueSample(
-      "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-      FetchAccountCapabilitiesFromSystemLibraryResult::kErrorMissingCapability,
-      1);
-}
+TEST_F(ChromeIdentityServiceTest, IsSubjectToParentalControls) {
+  service_.SetCapabilityUnderTest(
+      @(kIsSubjectToParentalControlsCapabilityName),
+      ^(ChromeIdentityCapabilityResult* fetched_capability_result) {
+        service_.IsSubjectToParentalControls(
+            identity_, ^(ChromeIdentityCapabilityResult result) {
+              *fetched_capability_result = result;
+            });
+      });
 
-TEST_F(ChromeIdentityServiceTest,
-       CanOfferExtendedSyncPromos_UnexpectedCapabilityValue) {
-  base::HistogramTester histogramTester;
-  // Capability value of 100 is out of range.
-  EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
-            FetchCanOfferExtendedSyncPromos(
-                identity_, /*capability_value=*/[NSNumber numberWithInt:100],
-                /*error=*/nil));
-  histogramTester.ExpectUniqueSample(
-      "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-      FetchAccountCapabilitiesFromSystemLibraryResult::kErrorUnexpectedValue,
-      1);
-}
-
-TEST_F(ChromeIdentityServiceTest, CanOfferExtendedSyncPromos_Error) {
-  NSError* error = [NSError errorWithDomain:@"test" code:-100 userInfo:nil];
-
-  {
-    base::HistogramTester histogramTester;
-    EXPECT_EQ(ChromeIdentityCapabilityResult::kUnknown,
-              FetchCanOfferExtendedSyncPromos(identity_,
-                                              /*capability_value=*/nil, error));
-    histogramTester.ExpectUniqueSample(
-        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-        FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
-  }
-
-  {
-    base::HistogramTester histogramTester;
-    EXPECT_EQ(
-        ChromeIdentityCapabilityResult::kUnknown,
-        FetchCanOfferExtendedSyncPromos(
-            identity_, /*capability_value=*/[NSNumber numberWithInt:0], error));
-    histogramTester.ExpectUniqueSample(
-        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-        FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
-  }
-  {
-    base::HistogramTester histogramTester;
-    EXPECT_EQ(
-        ChromeIdentityCapabilityResult::kUnknown,
-        FetchCanOfferExtendedSyncPromos(
-            identity_, /*capability_value=*/[NSNumber numberWithInt:1], error));
-    histogramTester.ExpectUniqueSample(
-        "Signin.AccountCapabilities.GetFromSystemLibraryResult",
-        FetchAccountCapabilitiesFromSystemLibraryResult::kErrorGeneric, 1);
-  }
-}
-
-TEST_F(ChromeIdentityServiceTest, CanOfferExtendedSyncPromos_Histogram) {
-  base::HistogramTester histogramTester;
-  base::ScopedMockClockOverride clock;
-  service_.CanOfferExtendedSyncPromos(identity_, /*callback=*/nil);
-  clock.Advance(base::Minutes(1));
-  service_.RunFinishCapabilitiesCompletion(
-      @{@(kCanOfferExtendedChromeSyncPromosCapabilityName) : @0},
-      /*error=*/nil);
-  histogramTester.ExpectUniqueTimeSample(
-      "Signin.AccountCapabilities.GetFromSystemLibraryDuration",
-      base::Minutes(1),
-      /*expected_bucket_count=*/1);
+  RunCapabilitySmokeTests();
 }
 
 }  // namespace
diff --git a/media/webrtc/audio_processor.cc b/media/webrtc/audio_processor.cc
index 3d2eff9..eb43361 100644
--- a/media/webrtc/audio_processor.cc
+++ b/media/webrtc/audio_processor.cc
@@ -191,12 +191,14 @@
     DeliverProcessedAudioCallback deliver_processed_audio_callback,
     LogCallback log_callback,
     const AudioProcessingSettings& settings,
-    const media::AudioParameters& input_format)
+    const media::AudioParameters& input_format,
+    const media::AudioParameters& output_format)
     : settings_(settings),
       webrtc_audio_processing_(
           media::CreateWebRtcAudioProcessingModule(settings)),
       log_callback_(std::move(log_callback)),
       input_format_(input_format),
+      output_format_(output_format),
       deliver_processed_audio_callback_(
           std::move(deliver_processed_audio_callback)),
       audio_delay_stats_reporter_(kBuffersPerSecond) {
@@ -206,88 +208,35 @@
       "%s({multi_channel_capture_processing=%s})", __func__,
       settings_.multi_channel_capture_processing ? "true" : "false"));
 
-  DCHECK(input_format_.IsValid());
-  SendLogMessage(
-      base::StringPrintf("%s({input_format_=[%s]})", __func__,
-                         input_format_.AsHumanReadableString().c_str()));
-
-  // TODO(crbug/881275): For now, we assume fixed parameters for the output when
-  // audio processing is enabled, to match the previous behavior. We should
-  // either use the input parameters (in which case, audio processing will
-  // convert at output) or ideally, have a backchannel from the sink to know
-  // what format it would prefer.
-  const int output_sample_rate =
-      webrtc_audio_processing_ ?
-#if BUILDFLAG(IS_CHROMECAST)
-                               std::min(media::kAudioProcessingSampleRateHz,
-                                        input_format_.sample_rate())
-#else
-                               media::kAudioProcessingSampleRateHz
-#endif  // BUILDFLAG(IS_CHROMECAST)
-                               : input_format_.sample_rate();
-
-  const int fifo_output_channels = input_format_.channels();
-
-  media::ChannelLayout output_channel_layout;
-  if (!webrtc_audio_processing_) {
-    output_channel_layout = input_format.channel_layout();
-  } else if (settings_.multi_channel_capture_processing) {
-    // The number of output channels is equal to the number of input channels.
-    // If the media stream audio processor receives stereo input it will output
-    // stereo. To reduce computational complexity, APM will not perform full
-    // multichannel processing unless any sink requests more than one channel.
-    // If the input is multichannel but the sinks are not interested in more
-    // than one channel, APM will internally downmix the signal to mono and
-    // process it. The processed mono signal will then be upmixed to same number
-    // of channels as the input before leaving the media stream audio processor.
-    // If a sink later requests stereo, APM will start performing true stereo
-    // processing. There will be no need to change the output format.
-
-    output_channel_layout = input_format.channel_layout();
-  } else {
-    output_channel_layout = media::CHANNEL_LAYOUT_MONO;
+  CHECK(input_format_.IsValid());
+  CHECK(output_format_.IsValid());
+  if (settings.NeedWebrtcAudioProcessing()) {
+    DCHECK(!!webrtc_audio_processing_);
+    DCHECK_EQ(output_format_.sample_rate() / 100,
+              output_format_.frames_per_buffer());
   }
-
-  // webrtc::AudioProcessing requires a 10 ms chunk size. We use this native
-  // size when processing is enabled. When disabled we use the same size as
-  // the source if less than 10 ms.
-  //
-  // TODO(ajm): This conditional buffer size appears to be assuming knowledge of
-  // the sink based on the source parameters. PeerConnection sinks seem to want
-  // 10 ms chunks regardless, while WebAudio sinks want less, and we're assuming
-  // we can identify WebAudio sinks by the input chunk size. Less fragile would
-  // be to have the sink actually tell us how much it wants (as in the above
-  // todo).
-  int processing_frames = input_format.sample_rate() / 100;
-  int output_frames = output_sample_rate / 100;
-  if (!webrtc_audio_processing_ &&
-      input_format.frames_per_buffer() < output_frames) {
-    processing_frames = input_format.frames_per_buffer();
-    output_frames = processing_frames;
-  }
-
-  output_format_ = media::AudioParameters(
-      media::AudioParameters::AUDIO_PCM_LOW_LATENCY, output_channel_layout,
-      output_sample_rate, output_frames);
-  if (output_channel_layout == media::CHANNEL_LAYOUT_DISCRETE) {
-    // Explicitly set number of channels for discrete channel layouts.
-    output_format_.set_channels_for_discrete(input_format.channels());
-  }
-  SendLogMessage(
-      base::StringPrintf("%s => (output_format=[%s])", __func__,
-                         output_format_.AsHumanReadableString().c_str()));
   SendLogMessage(base::StringPrintf(
-      "%s => (FIFO: processing_frames=%d, output_channels=%d)", __func__,
-      processing_frames, fifo_output_channels));
+      "%s({input_format_=[%s], output_format_=[%s]})", __func__,
+      input_format_.AsHumanReadableString().c_str(),
+      output_format_.AsHumanReadableString().c_str()));
 
+  // If audio processing is needed, rebuffer to 10 ms. If not, rebuffer to the
+  // requested output format.
+  const int fifo_output_frames_per_buffer =
+      settings_.NeedWebrtcAudioProcessing()
+          ? input_format_.sample_rate() / 100
+          : output_format_.frames_per_buffer();
+  SendLogMessage(
+      base::StringPrintf("%s => (FIFO: fifo_output_frames_per_buffer=%d)",
+                         __func__, fifo_output_frames_per_buffer));
   capture_fifo_ = std::make_unique<AudioProcessorCaptureFifo>(
-      input_format.channels(), fifo_output_channels,
-      input_format.frames_per_buffer(), processing_frames,
+      input_format.channels(), input_format_.channels(),
+      input_format.frames_per_buffer(), fifo_output_frames_per_buffer,
       input_format.sample_rate());
 
   if (webrtc_audio_processing_) {
     output_bus_ = std::make_unique<AudioProcessorCaptureBus>(
-        output_format_.channels(), output_frames);
+        output_format_.channels(), output_format.frames_per_buffer());
   }
 }
 
@@ -557,4 +506,69 @@
                                        reinterpret_cast<uintptr_t>(this)));
 }
 
+// If WebRTC audio processing is used, the default output format is fixed to the
+// native WebRTC processing format in order to avoid rebuffering and resampling.
+// If not, then the input format is essentially preserved.
+// static
+AudioParameters AudioProcessor::GetDefaultOutputFormat(
+    const AudioParameters& input_format,
+    const AudioProcessingSettings& settings) {
+  const bool need_webrtc_audio_processing =
+      settings.NeedWebrtcAudioProcessing();
+  const int output_sample_rate =
+      need_webrtc_audio_processing ?
+#if BUILDFLAG(IS_CHROMECAST)
+                                   std::min(media::kAudioProcessingSampleRateHz,
+                                            input_format.sample_rate())
+#else
+                                   media::kAudioProcessingSampleRateHz
+#endif  // BUILDFLAG(IS_CHROMECAST)
+                                   : input_format.sample_rate();
+
+  media::ChannelLayout output_channel_layout;
+  if (!need_webrtc_audio_processing) {
+    output_channel_layout = input_format.channel_layout();
+  } else if (settings.multi_channel_capture_processing) {
+    // The number of output channels is equal to the number of input channels.
+    // If the media stream audio processor receives stereo input it will
+    // output stereo. To reduce computational complexity, APM will not perform
+    // full multichannel processing unless any sink requests more than one
+    // channel. If the input is multichannel but the sinks are not interested
+    // in more than one channel, APM will internally downmix the signal to
+    // mono and process it. The processed mono signal will then be upmixed to
+    // same number of channels as the input before leaving the media stream
+    // audio processor. If a sink later requests stereo, APM will start
+    // performing true stereo processing. There will be no need to change the
+    // output format.
+
+    output_channel_layout = input_format.channel_layout();
+  } else {
+    output_channel_layout = media::CHANNEL_LAYOUT_MONO;
+  }
+
+  // webrtc::AudioProcessing requires a 10 ms chunk size. We use this native
+  // size when processing is enabled. When disabled we use the same size as
+  // the source if less than 10 ms.
+  //
+  // TODO(ajm): This conditional buffer size appears to be assuming knowledge of
+  // the sink based on the source parameters. PeerConnection sinks seem to want
+  // 10 ms chunks regardless, while WebAudio sinks want less, and we're assuming
+  // we can identify WebAudio sinks by the input chunk size. Less fragile would
+  // be to have the sink actually tell us how much it wants (as in the above
+  // todo).
+  int output_frames = output_sample_rate / 100;
+  if (!need_webrtc_audio_processing &&
+      input_format.frames_per_buffer() < output_frames) {
+    output_frames = input_format.frames_per_buffer();
+  }
+
+  media::AudioParameters output_format = media::AudioParameters(
+      media::AudioParameters::AUDIO_PCM_LOW_LATENCY, output_channel_layout,
+      output_sample_rate, output_frames);
+  if (output_channel_layout == media::CHANNEL_LAYOUT_DISCRETE) {
+    // Explicitly set number of channels for discrete channel layouts.
+    output_format.set_channels_for_discrete(input_format.channels());
+  }
+  return output_format;
+}
 }  // namespace media
diff --git a/media/webrtc/audio_processor.h b/media/webrtc/audio_processor.h
index 967c563..523775e 100644
--- a/media/webrtc/audio_processor.h
+++ b/media/webrtc/audio_processor.h
@@ -59,13 +59,17 @@
 
   // |deliver_processed_audio_callback| is used to deliver frames of processed
   // capture audio, from ProcessCapturedAudio(), and has to be valid for as long
-  // as ProcessCapturedAudio() may be called. |log_callback| is used for logging
-  // messages on the owning sequence. |input_format| is a format of the capture
-  // data.
+  // as ProcessCapturedAudio() may be called.
+  // |log_callback| is used for logging messages on the owning sequence.
+  // |input_format| specifies the format of the incoming capture data.
+  // |output_format| specifies the output format. If
+  // |settings.NeedWebrtcAudioProcessing()| is true, then the output must be in
+  // 10 ms chunks.
   AudioProcessor(DeliverProcessedAudioCallback deliver_processed_audio_callback,
                  LogCallback log_callback,
                  const AudioProcessingSettings& settings,
-                 const media::AudioParameters& input_format);
+                 const media::AudioParameters& input_format,
+                 const media::AudioParameters& output_format);
 
   ~AudioProcessor();
 
@@ -141,6 +145,12 @@
     return input_format_;
   }
 
+  // Returns an output format that minimizes delay and resampling for a given
+  // input format.
+  static AudioParameters GetDefaultOutputFormat(
+      const AudioParameters& input_format,
+      const AudioProcessingSettings& settings);
+
  private:
   friend class AudioProcessorTest;
 
@@ -198,10 +208,9 @@
   // Receives APM processing output.
   std::unique_ptr<AudioProcessorCaptureBus> output_bus_;
 
-  // Input and output formats for capture processing. |output_format_| is
-  // initialized once in the constructor, so is essentially const as well.
+  // Input and output formats for capture processing.
   const media::AudioParameters input_format_;
-  media::AudioParameters output_format_;
+  const media::AudioParameters output_format_;
 
   // Members accessed only on the capture thread:
 
diff --git a/media/webrtc/audio_processor_test.cc b/media/webrtc/audio_processor_test.cc
index db86b1f9..1e92d86 100644
--- a/media/webrtc/audio_processor_test.cc
+++ b/media/webrtc/audio_processor_test.cc
@@ -15,6 +15,7 @@
 #include "base/logging.h"
 #include "base/memory/aligned_memory.h"
 #include "base/path_service.h"
+#include "base/strings/stringprintf.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
@@ -35,6 +36,18 @@
 namespace media {
 namespace {
 
+static const int kSupportedSampleRates[] = {8000,
+                                            16000,
+                                            22050,
+                                            32000,
+                                            44100,
+                                            48000
+#if BUILDFLAG(IS_CHROMECAST)
+                                            ,
+                                            96000
+#endif  // BUILDFLAG(IS_CHROMECAST)
+};
+
 using MockProcessedCaptureCallback =
     base::MockRepeatingCallback<void(const media::AudioBus& audio_bus,
                                      base::TimeTicks audio_capture_time,
@@ -88,13 +101,12 @@
   // Helper method to save duplicated code.
   static void ProcessDataAndVerifyFormat(
       AudioProcessor& audio_processor,
-      MockProcessedCaptureCallback& mock_capture_callback,
-      int expected_output_sample_rate,
-      int expected_output_channels,
-      int expected_output_buffer_size) {
+      MockProcessedCaptureCallback& mock_capture_callback) {
     // Read the audio data from a file.
     const media::AudioParameters& params =
         audio_processor.GetInputFormatForTesting();
+    const media::AudioParameters& output_params =
+        audio_processor.OutputFormat();
     const int packet_size = params.frames_per_buffer() * 2 * params.channels();
     const size_t length = packet_size * kNumberOfPacketsForTest;
     std::unique_ptr<char[]> capture_data(new char[length]);
@@ -125,16 +137,13 @@
           .WillRepeatedly([&](const media::AudioBus& processed_audio,
                               base::TimeTicks audio_capture_time,
                               absl::optional<double> new_volume) {
+            EXPECT_EQ(processed_audio.channels(), output_params.channels());
+            EXPECT_EQ(processed_audio.frames(),
+                      output_params.frames_per_buffer());
             EXPECT_EQ(audio_capture_time, input_capture_time);
           });
       audio_processor.ProcessCapturedAudio(*data_bus, input_capture_time,
                                            num_preferred_channels, 1.0, false);
-      EXPECT_EQ(expected_output_sample_rate,
-                audio_processor.OutputFormat().sample_rate());
-      EXPECT_EQ(expected_output_channels,
-                audio_processor.OutputFormat().channels());
-      EXPECT_EQ(expected_output_buffer_size,
-                audio_processor.OutputFormat().frames_per_buffer());
 
       data_ptr += params.frames_per_buffer() * params.channels();
 
@@ -174,9 +183,32 @@
   base::test::TaskEnvironment task_environment_;
 };
 
-class AudioProcessorTestMultichannel
+struct AudioProcessorTestMultichannelAndFormat
     : public AudioProcessorTest,
-      public ::testing::WithParamInterface<bool> {};
+      public ::testing::WithParamInterface<std::tuple<bool, bool>> {
+  AudioParameters GetProcessorOutputParams(
+      const AudioParameters& params,
+      const AudioProcessingSettings& settings) {
+    const bool use_input_format_for_output = std::get<1>(GetParam());
+    return use_input_format_for_output
+               ? params
+               : AudioProcessor::GetDefaultOutputFormat(params, settings);
+  }
+
+  static std::string PrintTestName(
+      const testing::TestParamInfo<ParamType>& info) {
+    auto [multichannel, input_format_for_output] = info.param;
+    return base::StringPrintf("MultichannelApm%sSameInputOutputFormat%s",
+                              multichannel ? "True" : "False",
+                              input_format_for_output ? "True" : "False");
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    /*no prefix*/,
+    AudioProcessorTestMultichannelAndFormat,
+    ::testing::Combine(::testing::Bool(), ::testing::Bool()),
+    &AudioProcessorTestMultichannelAndFormat::PrintTestName);
 
 // Test crashing with ASAN on Android. crbug.com/468762
 #if BUILDFLAG(IS_ANDROID) && defined(ADDRESS_SANITIZER)
@@ -184,34 +216,34 @@
 #else
 #define MAYBE_WithAudioProcessing WithAudioProcessing
 #endif
-TEST_P(AudioProcessorTestMultichannel, MAYBE_WithAudioProcessing) {
-  const bool use_multichannel_processing = GetParam();
+TEST_P(AudioProcessorTestMultichannelAndFormat, MAYBE_WithAudioProcessing) {
   AudioProcessingSettings settings{.multi_channel_capture_processing =
-                                       use_multichannel_processing};
+                                       std::get<0>(GetParam())};
   AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                 LogCallbackForTesting(), settings, params_);
+                                 LogCallbackForTesting(), settings, params_,
+                                 GetProcessorOutputParams(params_, settings));
   EXPECT_TRUE(audio_processor.has_webrtc_audio_processing());
   VerifyDefaultComponents(audio_processor);
 
-  const int expected_output_channels =
-      use_multichannel_processing ? params_.channels() : 1;
-  ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_,
-                             media::kAudioProcessingSampleRateHz,
-                             expected_output_channels,
-                             media::kAudioProcessingSampleRateHz / 100);
+  ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_);
 }
 
 TEST_F(AudioProcessorTest, TurnOffDefaultConstraints) {
   AudioProcessingSettings settings;
   // Turn off the default settings and pass it to AudioProcessor.
   DisableDefaultSettings(settings);
-  AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                 LogCallbackForTesting(), settings, params_);
+  AudioProcessor audio_processor(
+      mock_capture_callback_.Get(), LogCallbackForTesting(), settings, params_,
+      AudioProcessor::GetDefaultOutputFormat(params_, settings));
   EXPECT_FALSE(audio_processor.has_webrtc_audio_processing());
 
-  ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_,
-                             params_.sample_rate(), params_.channels(),
-                             params_.sample_rate() / 100);
+  EXPECT_EQ(audio_processor.OutputFormat().sample_rate(),
+            params_.sample_rate());
+  EXPECT_EQ(audio_processor.OutputFormat().channels(), params_.channels());
+  EXPECT_EQ(audio_processor.OutputFormat().frames_per_buffer(),
+            params_.sample_rate() / 100);
+
+  ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_);
 }
 
 // Test crashing with ASAN on Android. crbug.com/468762
@@ -220,23 +252,10 @@
 #else
 #define MAYBE_TestAllSampleRates TestAllSampleRates
 #endif
-TEST_P(AudioProcessorTestMultichannel, MAYBE_TestAllSampleRates) {
-  const bool use_multichannel_processing = GetParam();
+TEST_P(AudioProcessorTestMultichannelAndFormat, MAYBE_TestAllSampleRates) {
   AudioProcessingSettings settings{.multi_channel_capture_processing =
-                                       use_multichannel_processing};
+                                       std::get<0>(GetParam())};
 
-  static const int kSupportedSampleRates[] = {
-    8000,
-    16000,
-    22050,
-    32000,
-    44100,
-    48000
-#if BUILDFLAG(IS_CHROMECAST)
-    ,
-    96000
-#endif  // BUILDFLAG(IS_CHROMECAST)
-  };
   for (int sample_rate : kSupportedSampleRates) {
     SCOPED_TRACE(testing::Message() << "sample_rate=" << sample_rate);
     int buffer_size = sample_rate / 100;
@@ -244,35 +263,26 @@
                                   media::CHANNEL_LAYOUT_STEREO, sample_rate,
                                   buffer_size);
     AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                   LogCallbackForTesting(), settings, params);
+                                   LogCallbackForTesting(), settings, params,
+                                   GetProcessorOutputParams(params, settings));
     EXPECT_TRUE(audio_processor.has_webrtc_audio_processing());
     VerifyDefaultComponents(audio_processor);
 
-    int expected_sample_rate =
-#if BUILDFLAG(IS_CHROMECAST)
-        std::min(sample_rate, media::kAudioProcessingSampleRateHz);
-#else
-        media::kAudioProcessingSampleRateHz;
-#endif  // BUILDFLAG(IS_CHROMECAST)
-    const int expected_output_channels =
-        use_multichannel_processing ? params_.channels() : 1;
-    ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_,
-                               expected_sample_rate, expected_output_channels,
-                               expected_sample_rate / 100);
+    ProcessDataAndVerifyFormat(audio_processor, mock_capture_callback_);
   }
 }
 
 TEST_F(AudioProcessorTest, StartStopAecDump) {
-  AudioProcessingSettings settings;
-
   base::ScopedTempDir temp_directory;
   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
   base::FilePath temp_file_path;
   ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.GetPath(),
                                              &temp_file_path));
   {
-    AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                   LogCallbackForTesting(), settings, params_);
+    AudioProcessingSettings settings;
+    AudioProcessor audio_processor(
+        mock_capture_callback_.Get(), LogCallbackForTesting(), settings,
+        params_, AudioProcessor::GetDefaultOutputFormat(params_, settings));
 
     // Start and stop recording.
     audio_processor.OnStartDump(base::File(
@@ -295,8 +305,6 @@
 }
 
 TEST_F(AudioProcessorTest, StartAecDumpDuringOngoingAecDump) {
-  AudioProcessingSettings settings;
-
   base::ScopedTempDir temp_directory;
   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
   base::FilePath temp_file_path_a;
@@ -306,8 +314,10 @@
   ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.GetPath(),
                                              &temp_file_path_b));
   {
-    AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                   LogCallbackForTesting(), settings, params_);
+    AudioProcessingSettings settings;
+    AudioProcessor audio_processor(
+        mock_capture_callback_.Get(), LogCallbackForTesting(), settings,
+        params_, AudioProcessor::GetDefaultOutputFormat(params_, settings));
 
     // Start a recording.
     audio_processor.OnStartDump(base::File(
@@ -330,24 +340,19 @@
   // The temporary files are deleted when temp_directory exits scope.
 }
 
-TEST_P(AudioProcessorTestMultichannel, TestStereoAudio) {
-  const bool use_multichannel_processing = GetParam();
-  SCOPED_TRACE(testing::Message() << "use_multichannel_processing="
-                                  << use_multichannel_processing);
-  const media::AudioParameters source_params(
-      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
-      media::CHANNEL_LAYOUT_STEREO, 48000, 480);
+TEST_P(AudioProcessorTestMultichannelAndFormat, TestStereoAudio) {
+  const bool use_multichannel_processing = std::get<0>(GetParam());
 
   // Construct left and right channels, and populate each channel with
   // different values.
-  const int size = media::AudioBus::CalculateMemorySize(source_params);
+  const int size = media::AudioBus::CalculateMemorySize(params_);
   std::unique_ptr<float, base::AlignedFreeDeleter> left_channel(
       static_cast<float*>(base::AlignedAlloc(size, 32)));
   std::unique_ptr<float, base::AlignedFreeDeleter> right_channel(
       static_cast<float*>(base::AlignedAlloc(size, 32)));
   std::unique_ptr<media::AudioBus> wrapper =
-      media::AudioBus::CreateWrapper(source_params.channels());
-  wrapper->set_frames(source_params.frames_per_buffer());
+      media::AudioBus::CreateWrapper(params_.channels());
+  wrapper->set_frames(params_.frames_per_buffer());
   wrapper->SetChannelData(0, left_channel.get());
   wrapper->SetChannelData(1, right_channel.get());
   wrapper->Zero();
@@ -370,8 +375,8 @@
     // Turn on the stereo channels mirroring.
     settings.stereo_mirroring = true;
     AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                   LogCallbackForTesting(), settings,
-                                   source_params);
+                                   LogCallbackForTesting(), settings, params_,
+                                   GetProcessorOutputParams(params_, settings));
     EXPECT_EQ(audio_processor.has_webrtc_audio_processing(), use_apm);
     // There's no sense in continuing if this fails.
     ASSERT_EQ(2, audio_processor.OutputFormat().channels());
@@ -422,6 +427,49 @@
   }
 }
 
+struct AudioProcessorDefaultOutputFormatTest
+    : public ::testing::Test,
+      public ::testing::WithParamInterface<std::tuple<bool, int>> {
+  static std::string PrintTestName(
+      const testing::TestParamInfo<ParamType>& info) {
+    auto [multichannel, sample_rate] = info.param;
+    return base::StringPrintf("MultichannelApm%sSampleRate%d",
+                              multichannel ? "True" : "False", sample_rate);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+    /*no prefix*/,
+    AudioProcessorDefaultOutputFormatTest,
+    ::testing::Combine(::testing::Bool(),
+                       ::testing::ValuesIn(kSupportedSampleRates)),
+    &AudioProcessorDefaultOutputFormatTest::PrintTestName);
+
+TEST_P(AudioProcessorDefaultOutputFormatTest, GetDefaultOutputFormat) {
+  AudioProcessingSettings settings{.multi_channel_capture_processing =
+                                       std::get<0>(GetParam())};
+  const int sample_rate = std::get<1>(GetParam());
+
+  media::AudioParameters input_params(
+      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+      media::CHANNEL_LAYOUT_STEREO, sample_rate, sample_rate / 100);
+  AudioParameters output_params =
+      AudioProcessor::GetDefaultOutputFormat(input_params, settings);
+
+  const int expected_sample_rate =
+#if BUILDFLAG(IS_CHROMECAST)
+      std::min(sample_rate, media::kAudioProcessingSampleRateHz);
+#else
+      media::kAudioProcessingSampleRateHz;
+#endif  // BUILDFLAG(IS_CHROMECAST)
+  const int expected_output_channels =
+      settings.multi_channel_capture_processing ? input_params.channels() : 1;
+
+  EXPECT_EQ(output_params.sample_rate(), expected_sample_rate);
+  EXPECT_EQ(output_params.channels(), expected_output_channels);
+  EXPECT_EQ(output_params.frames_per_buffer(), expected_sample_rate / 100);
+}
+
 // Ensure that discrete channel layouts do not crash with audio processing
 // enabled.
 TEST_F(AudioProcessorTest, DiscreteChannelLayout) {
@@ -432,16 +480,13 @@
   // Test both 1 and 2 discrete channels.
   for (int channels = 1; channels <= 2; ++channels) {
     params.set_channels_for_discrete(channels);
-    AudioProcessor audio_processor(mock_capture_callback_.Get(),
-                                   LogCallbackForTesting(), settings, params);
+    AudioProcessor audio_processor(
+        mock_capture_callback_.Get(), LogCallbackForTesting(), settings, params,
+        AudioProcessor::GetDefaultOutputFormat(params, settings));
     EXPECT_TRUE(audio_processor.has_webrtc_audio_processing());
   }
 }
 
-INSTANTIATE_TEST_SUITE_P(AudioProcessorMultichannelAffectedTests,
-                         AudioProcessorTestMultichannel,
-                         ::testing::Values(false, true));
-
 // When audio processing is performed, processed audio should be delivered as
 // soon as 10 ms of audio has been received.
 TEST(AudioProcessorCallbackTest,
@@ -452,8 +497,9 @@
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 media::CHANNEL_LAYOUT_STEREO, 48000,
                                 48000 * 4 / 1000);
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params,
+      AudioProcessor::GetDefaultOutputFormat(params, settings));
   ASSERT_TRUE(audio_processor.has_webrtc_audio_processing());
   int output_sample_rate = audio_processor.OutputFormat().sample_rate();
   std::unique_ptr<media::AudioBus> data_bus =
@@ -501,8 +547,9 @@
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 media::CHANNEL_LAYOUT_STEREO, 48000,
                                 48000 * 35 / 1000);
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params,
+      AudioProcessor::GetDefaultOutputFormat(params, settings));
   ASSERT_TRUE(audio_processor.has_webrtc_audio_processing());
   int output_sample_rate = audio_processor.OutputFormat().sample_rate();
   std::unique_ptr<media::AudioBus> data_bus =
@@ -540,8 +587,9 @@
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 media::CHANNEL_LAYOUT_STEREO, 48000,
                                 48000 * 4 / 1000);
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params,
+      AudioProcessor::GetDefaultOutputFormat(params, settings));
   ASSERT_FALSE(audio_processor.has_webrtc_audio_processing());
   int output_sample_rate = audio_processor.OutputFormat().sample_rate();
   std::unique_ptr<media::AudioBus> data_bus =
@@ -576,8 +624,9 @@
   media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 media::CHANNEL_LAYOUT_STEREO, 48000,
                                 48000 * 35 / 1000);
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params,
+      AudioProcessor::GetDefaultOutputFormat(params, settings));
   ASSERT_FALSE(audio_processor.has_webrtc_audio_processing());
   int output_sample_rate = audio_processor.OutputFormat().sample_rate();
   std::unique_ptr<media::AudioBus> data_bus =
@@ -609,8 +658,9 @@
   AudioProcessingSettings settings;
   DisableDefaultSettings(settings);
   settings.echo_cancellation = true;
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params_);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params_,
+      AudioProcessor::GetDefaultOutputFormat(params_, settings));
   EXPECT_TRUE(audio_processor.RequiresPlayoutReference());
 }
 
@@ -619,8 +669,9 @@
   AudioProcessingSettings settings;
   DisableDefaultSettings(settings);
   settings.automatic_gain_control = true;
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params_);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params_,
+      AudioProcessor::GetDefaultOutputFormat(params_, settings));
   EXPECT_TRUE(audio_processor.RequiresPlayoutReference());
 }
 
@@ -638,8 +689,9 @@
   settings.high_pass_filter = true;
   settings.stereo_mirroring = true;
   settings.force_apm_creation = true;
-  AudioProcessor audio_processor(mock_capture_callback.Get(),
-                                 LogCallbackForTesting(), settings, params_);
+  AudioProcessor audio_processor(
+      mock_capture_callback.Get(), LogCallbackForTesting(), settings, params_,
+      AudioProcessor::GetDefaultOutputFormat(params_, settings));
   EXPECT_FALSE(audio_processor.RequiresPlayoutReference());
 }
 
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy.cc b/services/network/public/cpp/content_security_policy/content_security_policy.cc
index 30aeb02..897ab14 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -594,16 +594,15 @@
   if (base::EqualsCaseInsensitiveASCII(value, "'none'"))
     return directive;
 
-  for (const auto& expression : base::SplitStringPiece(
-           value, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
-           base::SPLIT_WANT_NONEMPTY)) {
+  std::vector<base::StringPiece> tokens =
+      base::SplitStringPiece(value, base::kWhitespaceASCII,
+                             base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  bool contains_none = false;
+
+  for (const auto& expression : tokens) {
     if (base::EqualsCaseInsensitiveASCII(expression, "'none'")) {
-      parsing_errors.emplace_back(base::StringPrintf(
-          "The Content-Security-Policy directive '%s' contains the keyword "
-          "'none' alongside with other source expressions. The keyword 'none' "
-          "must be the only source expression in the directive value, "
-          "otherwise it is ignored.",
-          ToString(directive_name).c_str()));
+      contains_none = true;
       continue;
     }
 
@@ -705,6 +704,19 @@
         ToString(directive_name).c_str(), std::string(expression).c_str()));
   }
 
+  if (contains_none &&
+      base::ranges::any_of(tokens, [](const auto& token) -> bool {
+        return !base::EqualsCaseInsensitiveASCII(token, "'report-sample'") &&
+               !base::EqualsCaseInsensitiveASCII(token, "'none'");
+      })) {
+    parsing_errors.emplace_back(base::StringPrintf(
+        "The Content-Security-Policy directive '%s' contains the keyword "
+        "'none' alongside with other source expressions. The keyword 'none' "
+        "must be the only source expression in the directive value, "
+        "otherwise it is ignored.",
+        ToString(directive_name).c_str()));
+  }
+
   return directive;
 }
 
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
index efb1c4f..25002af 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
@@ -1386,6 +1386,28 @@
           "otherwise it is ignored.",
       },
       {
+          "'none' 'report-sample'",
+          base::BindOnce([] {
+            auto csp = mojom::CSPSourceList::New();
+            csp->report_sample = true;
+            return csp;
+          }),
+          "",
+      },
+      {
+          "'none' 'self' 'report-sample'",
+          base::BindOnce([] {
+            auto csp = mojom::CSPSourceList::New();
+            csp->allow_self = true;
+            csp->report_sample = true;
+            return csp;
+          }),
+          "The Content-Security-Policy directive 'script-src' contains the "
+          "keyword 'none' alongside with other source expressions. The keyword "
+          "'none' must be the only source expression in the directive value, "
+          "otherwise it is ignored.",
+      },
+      {
           "'self'",
           base::BindOnce([] {
             auto csp = mojom::CSPSourceList::New();
diff --git a/services/network/web_transport.cc b/services/network/web_transport.cc
index cb1d93a8..4a632d1 100644
--- a/services/network/web_transport.cc
+++ b/services/network/web_transport.cc
@@ -48,22 +48,26 @@
     explicit StreamVisitor(Stream* stream)
         : stream_(stream->weak_factory_.GetWeakPtr()) {}
     ~StreamVisitor() override {
-      if (stream_) {
-        if (stream_->incoming_) {
-          stream_->writable_watcher_.Cancel();
-          stream_->writable_.reset();
-          stream_->transport_->client_->OnIncomingStreamClosed(
-              stream_->id_,
-              /*fin_received=*/false);
-          stream_->incoming_ = nullptr;
-        }
-        if (stream_->outgoing_) {
-          stream_->readable_watcher_.Cancel();
-          stream_->readable_.reset();
-          stream_->outgoing_ = nullptr;
-        }
-        stream_->MayDisposeLater();
+      Stream* stream = stream_.get();
+      if (!stream) {
+        return;
       }
+      if (stream->incoming_) {
+        stream->writable_watcher_.Cancel();
+        stream->writable_.reset();
+        if (stream->transport_->client_) {
+          stream->transport_->client_->OnIncomingStreamClosed(
+              stream->id_,
+              /*fin_received=*/false);
+        }
+        stream->incoming_ = nullptr;
+      }
+      if (stream->outgoing_) {
+        stream->readable_watcher_.Cancel();
+        stream->readable_.reset();
+        stream->outgoing_ = nullptr;
+      }
+      stream->MayDisposeLater();
     }
 
     // Visitor implementation:
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 6d209a0..ad9dec8 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1778,7 +1778,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R100-14488.0.0",
+        "cros_img": "atlas-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_ATLAS_LKGM",
         "resultdb": {
           "enable": true,
@@ -1793,7 +1793,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R99-14455.0.0",
+        "cros_img": "atlas-release/R99-14469.8.0",
         "name": "lacros_all_tast_tests_ATLAS_DEV",
         "resultdb": {
           "enable": true,
@@ -1838,7 +1838,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R100-14488.0.0",
+        "cros_img": "eve-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_EVE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1853,7 +1853,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R99-14455.0.0",
+        "cros_img": "eve-release/R99-14469.8.0",
         "name": "lacros_all_tast_tests_EVE_DEV",
         "resultdb": {
           "enable": true,
@@ -1943,7 +1943,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1958,7 +1958,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_HANA_LKGM",
         "resultdb": {
           "enable": true,
@@ -1973,7 +1973,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1987,7 +1987,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "ozone_unittests_HANA_LKGM",
         "resultdb": {
           "enable": true,
@@ -2001,7 +2001,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -2015,7 +2015,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "viz_unittests_HANA_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index f0962df..6692042 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -19385,392 +19385,6 @@
       }
     ]
   },
-  "android-bfcache-rel": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_android_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_android_browsertests",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "android_browsertests",
-        "test_id_prefix": "ninja://chrome/test:android_browsertests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--git-revision=${got_revision}"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_chrome_public_test_apk",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chrome-gold@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk",
-        "test_id_prefix": "ninja://chrome/android:chrome_public_test_apk/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--git-revision=${got_revision}"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_chrome_public_unit_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_chrome_public_unit_test_apk",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chrome-gold@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "chrome_public_unit_test_apk",
-        "test_id_prefix": "ninja://chrome/android:chrome_public_unit_test_apk/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_content_browsertests",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_content_shell_test_apk",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 5
-        },
-        "test": "content_shell_test_apk",
-        "test_id_prefix": "ninja://content/shell/android:content_shell_test_apk/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_content_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_content_unittests",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.unit_tests.filter",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "bf_cache_unit_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "bf_cache_unit_tests",
-        "resultdb": {
-          "enable": true,
-          "has_native_resultdb_integration": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "unit_tests",
-        "test_id_prefix": "ninja://chrome/test:unit_tests/"
-      }
-    ]
-  },
   "android-cronet-arm-dbg": {
     "additional_compile_targets": [
       "cronet_package",
@@ -33129,6 +32743,392 @@
       }
     ]
   },
+  "android-no-bfcache-rel": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_android_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_android_browsertests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "android_browsertests",
+        "test_id_prefix": "ninja://chrome/test:android_browsertests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--git-revision=${got_revision}"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_chrome_public_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_chrome_public_test_apk",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chrome-gold@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test": "chrome_public_test_apk",
+        "test_id_prefix": "ninja://chrome/android:chrome_public_test_apk/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--git-revision=${got_revision}"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_chrome_public_unit_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_chrome_public_unit_test_apk",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chrome-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "chrome_public_unit_test_apk",
+        "test_id_prefix": "ninja://chrome/android:chrome_public_unit_test_apk/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_content_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_content_browsertests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test": "content_browsertests",
+        "test_id_prefix": "ninja://content/test:content_browsertests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_content_shell_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_content_shell_test_apk",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 5
+        },
+        "test": "content_shell_test_apk",
+        "test_id_prefix": "ninja://content/shell/android:content_shell_test_apk/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_content_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_content_unittests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "content_unittests",
+        "test_id_prefix": "ninja://content/test:content_unittests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.unit_tests.filter",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "bf_cache_unit_tests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "bf_cache_unit_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "unit_tests",
+        "test_id_prefix": "ninja://chrome/test:unit_tests/"
+      }
+    ]
+  },
   "android-pie-arm64-coverage-experimental-rel": {
     "additional_compile_targets": [
       "validate_expectations"
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index cd193a3..9a72d007 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -10066,131 +10066,6 @@
       "all"
     ]
   },
-  "linux-bfcache-rel": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "bf_cache_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "bf_cache_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "bf_cache_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_unittests",
-        "test_id_prefix": "ninja://content/test:content_unittests/"
-      },
-      {
-        "args": [
-          "--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.unit_tests.filter"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "bf_cache_unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "unit_tests",
-        "test_id_prefix": "ninja://chrome/test:unit_tests/"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--num-retries=3",
-          "--flag-specific=enable-back-forward-cache-same-site",
-          "--ignore-tests=external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html"
-        ],
-        "isolate_name": "blink_web_tests",
-        "merge": {
-          "args": [
-            "--verbose"
-          ],
-          "script": "//third_party/blink/tools/merge_web_test_results.py"
-        },
-        "name": "blink_web_tests",
-        "resultdb": {
-          "enable": true
-        },
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 12
-        },
-        "test_id_prefix": "ninja://:blink_web_tests/"
-      }
-    ]
-  },
   "linux-bionic-rel": {
     "gtest_tests": [
       {
@@ -12142,6 +12017,130 @@
       "empty_main"
     ]
   },
+  "linux-no-bfcache-rel": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--disable-features=BackForwardCache"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "bf_cache_browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "browser_tests",
+        "test_id_prefix": "ninja://chrome/test:browser_tests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "bf_cache_content_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test": "content_browsertests",
+        "test_id_prefix": "ninja://content/test:content_browsertests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "bf_cache_content_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "content_unittests",
+        "test_id_prefix": "ninja://content/test:content_unittests/"
+      },
+      {
+        "args": [
+          "--disable-features=BackForwardCache",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.unit_tests.filter"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "bf_cache_unit_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "unit_tests",
+        "test_id_prefix": "ninja://chrome/test:unit_tests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--num-retries=3",
+          "--flag-specific=disable-bfcache"
+        ],
+        "isolate_name": "blink_web_tests",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "blink_web_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 12
+        },
+        "test_id_prefix": "ninja://:blink_web_tests/"
+      }
+    ]
+  },
   "linux-trusty-rel": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/filters/bfcache.unit_tests.filter b/testing/buildbot/filters/bfcache.unit_tests.filter
index 2d8f82a..27eb2770 100644
--- a/testing/buildbot/filters/bfcache.unit_tests.filter
+++ b/testing/buildbot/filters/bfcache.unit_tests.filter
@@ -1 +1 @@
-# These tests currently fail when run with --enable-features=BackForwardCache
+# These tests currently fail when run with --disable-features=BackForwardCache
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index e7f8674..89f7f07 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -304,6 +304,7 @@
     "type": "console_test_launcher",
   },
   "browser_tests": {
+    "python3": False,
     "label": "//chrome/test:browser_tests",
     "type": "windowed_test_launcher",
   },
@@ -728,6 +729,7 @@
     "type": "console_test_launcher",
   },
   "crashpad_tests": {
+    "python3": False,
     "label": "//third_party/crashpad/crashpad:crashpad_tests",
     "type": "console_test_launcher",
   },
@@ -967,6 +969,7 @@
     "type": "console_test_launcher",
   },
   "headless_browsertests": {
+    "python3": False,
     "label": "//headless:headless_browsertests",
     "type": "console_test_launcher",
   },
@@ -1555,6 +1558,7 @@
     "type": "additional_compile_target",
   },
   "remoting_unittests": {
+    "python3": False,
     "label": "//remoting:remoting_unittests",
     "type": "console_test_launcher",
   },
@@ -1639,6 +1643,7 @@
     "type": "console_test_launcher",
   },
   "services_unittests": {
+    "python3": False,
     "label": "//services:services_unittests",
     "type": "windowed_test_launcher",
   },
@@ -1881,6 +1886,7 @@
     "type": "windowed_test_launcher",
   },
   "unit_tests": {
+    "python3": False,
     "label": "//chrome/test:unit_tests",
     "type": "windowed_test_launcher",
   },
@@ -2145,6 +2151,7 @@
     ],
   },
   "zlib_unittests": {
+    "python3": False,
     "label": "//third_party/zlib:zlib_unittests",
     "type": "console_test_launcher",
   },
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 17f40ab..269d0eba 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1125,7 +1125,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R100-14488.0.0",
+        "cros_img": "octopus-release/R100-14490.0.0",
         "name": "lacros_fyi_tast_tests_OCTOPUS_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1136,7 +1136,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14455.0.0",
+        "cros_img": "octopus-release/R99-14469.8.0",
         "name": "lacros_fyi_tast_tests_OCTOPUS_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1169,7 +1169,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R100-14488.0.0",
+        "cros_img": "octopus-release/R100-14490.0.0",
         "name": "ozone_unittests_OCTOPUS_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1179,7 +1179,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14455.0.0",
+        "cros_img": "octopus-release/R99-14469.8.0",
         "name": "ozone_unittests_OCTOPUS_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1217,7 +1217,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1228,7 +1228,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "lacros_all_tast_tests_HANA_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1239,7 +1239,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1249,7 +1249,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "ozone_unittests_HANA_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1259,7 +1259,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R100-14488.0.0",
+        "cros_img": "kevin-release/R100-14490.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1269,7 +1269,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R100-14488.0.0",
+        "cros_img": "hana-release/R100-14490.0.0",
         "name": "viz_unittests_HANA_LKGM",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 4689c54..c8a5d4a 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -436,13 +436,6 @@
           '--release',
         ],
       },
-      'linux-bfcache-rel': {
-        'args': [
-          '--flag-specific=enable-back-forward-cache-same-site',
-          # TODO(crbug.com/1255537): Re-enable the test.
-          '--ignore-tests=external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html',
-        ],
-      },
       'linux-blink-animation-use-time-delta': {
         'args': [
           '--debug',
@@ -472,6 +465,11 @@
           '--flag-specific=enable-editing-ng',
         ],
       },
+      'linux-no-bfcache-rel': {
+        'args': [
+          '--flag-specific=disable-bfcache',
+        ],
+      },
       'linux-xenial-rel': {
         "args": [
           "--additional-env-var=LLVM_PROFILE_FILE=${ISOLATED_OUTDIR}/profraw/default-%2m.profraw",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 04436b9..d3ad22dc 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -407,13 +407,13 @@
     'bfcache_android_specific_gtests': {
       'bf_cache_android_browsertests': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'test': 'android_browsertests',
       },
       'bf_cache_chrome_public_test_apk': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 20,
@@ -426,7 +426,7 @@
       },
       'bf_cache_chrome_public_unit_test_apk': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'mixins': [
           'chrome-gold-service-account',
@@ -436,7 +436,7 @@
       },
       'bf_cache_content_shell_test_apk': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 5,
@@ -448,7 +448,7 @@
     'bfcache_generic_gtests': {
       'bf_cache_content_browsertests': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 20,
@@ -457,7 +457,7 @@
       },
       'bf_cache_content_unittests': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 10,
@@ -466,7 +466,7 @@
       },
       'bf_cache_unit_tests': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
           '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.unit_tests.filter'
         ],
         'swarming': {
@@ -479,7 +479,7 @@
     'bfcache_linux_specific_gtests': {
       'bf_cache_browser_tests': {
         'args': [
-          '--enable-features=BackForwardCache,BackForwardCacheSameSiteForBots,BackForwardCacheNoTimeEviction,ProactivelySwapBrowsingInstance',
+          '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 10,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 8741fac8..c1823b2 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -563,8 +563,8 @@
   'CROS_ATLAS_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '100.0.4857.0',
-      'cros_img': 'atlas-release/R100-14488.0.0',
+      'cros_chrome_version': '100.0.4859.0',
+      'cros_img': 'atlas-release/R100-14490.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_LKGM',
@@ -572,8 +572,8 @@
   'CROS_ATLAS_DEV': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '99.0.4827.0',
-      'cros_img': 'atlas-release/R99-14455.0.0',
+      'cros_chrome_version': '99.0.4844.14',
+      'cros_img': 'atlas-release/R99-14469.8.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_DEV',
@@ -599,8 +599,8 @@
   'CROS_EVE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '100.0.4857.0',
-      'cros_img': 'eve-release/R100-14488.0.0',
+      'cros_chrome_version': '100.0.4859.0',
+      'cros_img': 'eve-release/R100-14490.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_LKGM',
@@ -608,8 +608,8 @@
   'CROS_EVE_DEV': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '99.0.4827.0',
-      'cros_img': 'eve-release/R99-14455.0.0',
+      'cros_chrome_version': '99.0.4844.14',
+      'cros_img': 'eve-release/R99-14469.8.0',
     },
     'enabled': True,
     'identifier': 'EVE_DEV',
@@ -635,8 +635,8 @@
   'CROS_KEVIN_LKGM': {
     'skylab': {
       'cros_board': 'kevin',
-      'cros_chrome_version': '100.0.4857.0',
-      'cros_img': 'kevin-release/R100-14488.0.0',
+      'cros_chrome_version': '100.0.4859.0',
+      'cros_img': 'kevin-release/R100-14490.0.0',
     },
     'enabled': True,
     'identifier': 'KEVIN_LKGM',
@@ -644,8 +644,8 @@
   'CROS_HANA_LKGM': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '100.0.4857.0',
-      'cros_img': 'hana-release/R100-14488.0.0',
+      'cros_chrome_version': '100.0.4859.0',
+      'cros_img': 'hana-release/R100-14490.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_LKGM',
@@ -653,8 +653,8 @@
   'CROS_OCTOPUS_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '100.0.4857.0',
-      'cros_img': 'octopus-release/R100-14488.0.0',
+      'cros_chrome_version': '100.0.4859.0',
+      'cros_img': 'octopus-release/R100-14490.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_LKGM',
@@ -662,8 +662,8 @@
   'CROS_OCTOPUS_DEV': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '99.0.4827.0',
-      'cros_img': 'octopus-release/R99-14455.0.0',
+      'cros_chrome_version': '99.0.4844.14',
+      'cros_img': 'octopus-release/R99-14469.8.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_DEV',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 62d87fd..fa5ed1d 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -717,17 +717,6 @@
         },
         'os_type': 'android',
       },
-      'android-bfcache-rel': {
-        'mixins': [
-          'has_native_resultdb_integration',
-          'marshmallow',
-          'bullhead',
-        ],
-        'os_type': 'android',
-        'test_suites': {
-          'gtest_tests': 'bfcache_android_gtests',
-        }
-      },
       'android-cronet-arm-dbg': {
         'mixins': [
           'has_native_resultdb_integration',
@@ -997,6 +986,17 @@
           'isolated_scripts': 'marshmallow_nougat_pie_isolated_scripts_with_proguard',
         }
       },
+      'android-no-bfcache-rel': {
+        'mixins': [
+          'has_native_resultdb_integration',
+          'marshmallow',
+          'bullhead',
+        ],
+        'os_type': 'android',
+        'test_suites': {
+          'gtest_tests': 'bfcache_android_gtests',
+        }
+      },
       'android-pie-arm64-coverage-experimental-rel': {
         'mixins': [
           'has_native_resultdb_integration',
@@ -4983,15 +4983,6 @@
           'all',
         ],
       },
-      'linux-bfcache-rel': {
-        'mixins': [
-          'linux-bionic',
-        ],
-        'test_suites': {
-          'gtest_tests': 'bfcache_linux_gtests',
-          'isolated_scripts': 'chromium_webkit_isolated_scripts',
-        },
-      },
       'linux-bionic-rel': {
         'mixins': [
           'linux-bionic',
@@ -5012,6 +5003,15 @@
           'empty_main',
         ],
       },
+      'linux-no-bfcache-rel': {
+        'mixins': [
+          'linux-bionic',
+        ],
+        'test_suites': {
+          'gtest_tests': 'bfcache_linux_gtests',
+          'isolated_scripts': 'chromium_webkit_isolated_scripts',
+        },
+      },
       'linux-trusty-rel': {
         'mixins': [
           'linux-trusty',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 9345782..ede9563 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1070,7 +1070,7 @@
                         "blocked_websites": "https://domain1.org,https://domain2.org",
                         "cache_size": "6",
                         "content_injection_supported": "true",
-                        "enable_same_site": "false",
+                        "enable_same_site": "true",
                         "extension_message_supported": "true",
                         "file_system_api_supported": "true",
                         "foreground_cache_size": "2",
@@ -3672,6 +3672,21 @@
             ]
         }
     ],
+    "LacrosNonSyncingProfiles": [
+        {
+            "platforms": [
+                "chromeos_lacros"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "LacrosNonSyncingProfiles"
+                    ]
+                }
+            ]
+        }
+    ],
     "LightweightReactions": [
         {
             "platforms": [
@@ -5055,6 +5070,31 @@
                     ]
                 },
                 {
+                    "name": "EnabledExploreAndServerRankingSegmentation2",
+                    "params": {
+                        "base_url": "https://chromeupboarding-pa.googleapis.com",
+                        "experiment_tag": "{maxLevels : 1, rankTiles : true}",
+                        "image_prefetch_mode": "top",
+                        "is_unmetered_network_required": "false",
+                        "max_trending_tile_impressions": "1",
+                        "most_visited_max_rows_normal_screen": "1",
+                        "most_visited_max_rows_small_screen": "1",
+                        "mv_tile_click_threshold": "1",
+                        "small_screen_height_threshold_dp": "700"
+                    },
+                    "enable_features": [
+                        "QueryTiles",
+                        "QueryTilesInNTP",
+                        "QueryTilesLocalOrdering",
+                        "QueryTilesRemoveTrendingAfterInactivity",
+                        "QueryTilesSegmentation"
+                    ],
+                    "disable_features": [
+                        "QueryTilesEnableQueryEditing",
+                        "QueryTilesInOmnibox"
+                    ]
+                },
+                {
                     "name": "EnabledExploreAndServerRankingAndRawTrendingSegmentation2",
                     "params": {
                         "base_url": "https://chromeupboarding-pa.googleapis.com",
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index d8a3ff1..88e454b 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1386,6 +1386,9 @@
       # Container query list array (for rules involving container queries).
       # The array enumerates container queries starting with the innermost one, going outwards.
       experimental optional array of CSSContainerQuery containerQueries
+      # @supports CSS at-rule array.
+      # The array enumerates @supports at-rules starting with the innermost one, going outwards.
+      experimental optional array of CSSSupports supports
 
   # CSS coverage information.
   type RuleUsage extends object
@@ -1522,6 +1525,17 @@
       # Optional name for the container.
       optional string name
 
+  # CSS Supports at-rule descriptor.
+  experimental type CSSSupports extends object
+    properties
+      # Supports rule text.
+      string text
+      # The associated rule header range in the enclosing stylesheet (if
+      # available).
+      optional SourceRange range
+      # Identifier of the stylesheet containing this object (if exists).
+      optional StyleSheetId styleSheetId
+
   # Information about amount of glyphs that were rendered with given font.
   type PlatformFontUsage extends object
     properties
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index cc3292d..a9c90f8 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -490,7 +490,7 @@
     return false;
   }
 
-  if (*current != '%')
+  if (current == end || *current != '%')
     return false;
 
   ++current;
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
index dde37e8..e76575d 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
@@ -364,6 +364,10 @@
   // Junk after percentage.
   EXPECT_EQ(nullptr, CSSParserFastPaths::ParseColor(
                          "hsl(0.2, 50% foo, 20% 0.3)", kHTMLStandardMode));
+
+  // Stopping right before an expected %.
+  EXPECT_EQ(nullptr,
+            CSSParserFastPaths::ParseColor("hsl(9,0.6", kHTMLStandardMode));
 }
 
 TEST(CSSParserFastPathsTest, IsValidKeywordPropertyAndValueOverflowClip) {
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index f9867e2..647e4fc4 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -319,6 +319,19 @@
 
   bool InApplyAnimationUpdate() const { return in_apply_animation_update_; }
 
+  class InEnsureComputedStyleScope {
+    STACK_ALLOCATED();
+
+   public:
+    explicit InEnsureComputedStyleScope(StyleEngine& engine)
+        : auto_reset_(&engine.in_ensure_computed_style_, true) {}
+
+   private:
+    base::AutoReset<bool> auto_reset_;
+  };
+
+  bool InEnsureComputedStyle() const { return in_ensure_computed_style_; }
+
   void UpdateStyleInvalidationRoot(ContainerNode* ancestor, Node* dirty_node);
   void UpdateStyleRecalcRoot(ContainerNode* ancestor, Node* dirty_node);
   void UpdateLayoutTreeRebuildRoot(ContainerNode* ancestor, Node* dirty_node);
@@ -732,6 +745,7 @@
   bool in_detach_scope_{false};
 #endif  // DCHECK_IS_ON()
   bool in_apply_animation_update_{false};
+  bool in_ensure_computed_style_{false};
   bool viewport_style_dirty_{false};
   bool fonts_need_update_{false};
   bool counter_styles_need_update_{false};
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index b446179..1513011 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8232,7 +8232,8 @@
 
 bool Document::InStyleRecalc() const {
   return lifecycle_.GetState() == DocumentLifecycle::kInStyleRecalc ||
-         style_engine_->InContainerQueryStyleRecalc();
+         style_engine_->InContainerQueryStyleRecalc() ||
+         style_engine_->InEnsureComputedStyle();
 }
 
 void Document::DelayLoadEventUntilLayoutTreeUpdate() {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index c18d953..e072738 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -375,7 +375,8 @@
   if (style.IsDisplayInlineType())
     return false;
 
-  if (style.IsDisplayTableType())
+  if (style.IsDisplayTableType() &&
+      !RuntimeEnabledFeatures::LayoutNGTableFragmentationEnabled())
     return true;
 
   if (style.IsDisplayGridBox() &&
@@ -5405,6 +5406,9 @@
   // the V8 heap.
   DCHECK(ThreadState::Current()->IsAllocationAllowed());
 
+  StyleEngine::InEnsureComputedStyleScope ensure_scope(
+      GetDocument().GetStyleEngine());
+
   if (PseudoElement* element = GetPseudoElement(pseudo_element_specifier))
     return element->EnsureComputedStyle();
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index 032100a..928256d 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/core/css/css_rule_list.h"
 #include "third_party/blink/renderer/core/css/css_style_rule.h"
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
+#include "third_party/blink/renderer/core/css/css_supports_rule.h"
 #include "third_party/blink/renderer/core/css/css_variable_data.h"
 #include "third_party/blink/renderer/core/css/font_face.h"
 #include "third_party/blink/renderer/core/css/font_size_functions.h"
@@ -1907,6 +1908,48 @@
   return container_queries;
 }
 
+std::unique_ptr<protocol::CSS::CSSSupports>
+InspectorCSSAgent::BuildSupportsObject(CSSSupportsRule* rule) {
+  std::unique_ptr<protocol::CSS::CSSSupports> supports_object =
+      protocol::CSS::CSSSupports::create()
+          .setText(rule->ConditionTextInternal())
+          .build();
+
+  auto it =
+      css_style_sheet_to_inspector_style_sheet_.find(rule->parentStyleSheet());
+  if (it != css_style_sheet_to_inspector_style_sheet_.end()) {
+    InspectorStyleSheet* inspector_style_sheet = it->value;
+    supports_object->setStyleSheetId(inspector_style_sheet->Id());
+  }
+
+  InspectorStyleSheet* inspector_style_sheet =
+      BindStyleSheet(rule->parentStyleSheet());
+  supports_object->setRange(inspector_style_sheet->RuleHeaderSourceRange(rule));
+
+  return supports_object;
+}
+
+void InspectorCSSAgent::CollectSupportsFromRule(
+    CSSRule* rule,
+    protocol::Array<protocol::CSS::CSSSupports>* supports_list) {
+  if (auto* supports_rule = DynamicTo<CSSSupportsRule>(rule))
+    supports_list->emplace_back(BuildSupportsObject(supports_rule));
+}
+
+std::unique_ptr<protocol::Array<protocol::CSS::CSSSupports>>
+InspectorCSSAgent::BuildSupportsList(CSSRule* rule) {
+  if (!rule)
+    return nullptr;
+  auto supports_list =
+      std::make_unique<protocol::Array<protocol::CSS::CSSSupports>>();
+  CSSRule* parent_rule = rule;
+  while (parent_rule) {
+    CollectSupportsFromRule(parent_rule, supports_list.get());
+    parent_rule = parent_rule->parentRule();
+  }
+  return supports_list;
+}
+
 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::AsInspectorStyleSheet(
     Element* element) {
   NodeToInspectorStyleSheet::iterator it =
@@ -2085,6 +2128,7 @@
   result->setMedia(BuildMediaListChain(rule));
   if (RuntimeEnabledFeatures::CSSContainerQueriesEnabled())
     result->setContainerQueries(BuildContainerQueries(rule));
+  result->setSupports(BuildSupportsList(rule));
   return result;
 }
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/third_party/blink/renderer/core/inspector/inspector_css_agent.h
index f871eb2a..8fa2809 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.h
@@ -54,6 +54,7 @@
 class CSSRule;
 class CSSStyleRule;
 class CSSStyleSheet;
+class CSSSupportsRule;
 class Document;
 class Element;
 class FontCustomPlatformData;
@@ -340,6 +341,14 @@
   std::unique_ptr<protocol::Array<protocol::CSS::CSSContainerQuery>>
   BuildContainerQueries(CSSRule*);
 
+  // Supports at-rule implementation
+  std::unique_ptr<protocol::CSS::CSSSupports> BuildSupportsObject(
+      CSSSupportsRule*);
+  void CollectSupportsFromRule(CSSRule*,
+                               protocol::Array<protocol::CSS::CSSSupports>*);
+  std::unique_ptr<protocol::Array<protocol::CSS::CSSSupports>>
+  BuildSupportsList(CSSRule*);
+
   // InspectorDOMAgent::DOMListener implementation
   void DidAddDocument(Document*) override;
   void WillRemoveDOMNode(Node*) override;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index f31503d..14f2b62 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -315,6 +315,11 @@
 #endif
   }
 
+  // TODO(mstensho): We need to do more here (vertical alignment, for instance),
+  // if this is a table cell.
+  if (ConstraintSpace().IsTableCell())
+    container_builder_.SetIsTableNGPart();
+
   NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), &container_builder_).Run();
 
   return container_builder_.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index afd08f0..044d601 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
@@ -452,7 +453,7 @@
 }
 
 scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::Layout() {
-  DCHECK(!BreakToken());
+  DCHECK(!IsResumingLayout(BreakToken()));
 
   const bool is_fixed_layout = Style().IsFixedTableLayout();
   const LogicalSize border_spacing = Style().TableBorderSpacing();
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc
index f47a4ba..531d94e 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -319,6 +319,10 @@
   // streaming.
   DisableStreaming(ScriptStreamer::NotStreamingReason::kRevalidate);
 
+  // For the same reason, disable off-thread cache consumption.
+  cache_consumer_ = nullptr;
+  DisableOffThreadConsumeCache();
+
   TextResource::SetRevalidatingRequest(request);
 }
 
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
index d46f0ab..0163f5b 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -559,8 +559,6 @@
 }
 
 String WorkerOrWorkletGlobalScope::GetAcceptLanguages() const {
-  // TODO(crbug.com/1286059): Turn this CHECK into a DCHECK when the investigation is done.
-  CHECK(web_worker_fetch_context_);
   return web_worker_fetch_context_->GetAcceptLanguages();
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
index 67803d9..ec231e6 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
@@ -30,7 +30,10 @@
                        ConvertToBaseRepeatingCallback(
                            CrossThreadBindRepeating(&WebRtcLogMessage)),
                        settings,
-                       capture_data_source_params),
+                       capture_data_source_params,
+                       media::AudioProcessor::GetDefaultOutputFormat(
+                           capture_data_source_params,
+                           settings)),
       playout_data_source_(std::move(playout_data_source)),
       main_thread_runner_(base::ThreadTaskRunnerHandle::Get()),
       aec_dump_agent_impl_(AecDumpAgentImpl::Create(this)),
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
index 0da2f6de..716997b 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h
@@ -80,8 +80,7 @@
   void Stop();
 
   // The format of the processed capture output audio from the processor.
-  // Is constant between calls to OnCaptureFormatChanged().
-  // Must only be called on the main render thread.
+  // Is constant throughout MediaStreamAudioProcessor lifetime.
   const media::AudioParameters& OutputFormat() const;
 
   // Accessor to check if WebRTC audio processing is enabled or not.
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 763af4e..cfdfe6d 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -118,10 +118,6 @@
   RuntimeEnabledFeatures::SetAccessibilityAriaVirtualContentEnabled(enable);
 }
 
-void WebRuntimeFeatures::EnableAccessibilityExposeDisplayNone(bool enable) {
-  RuntimeEnabledFeatures::SetAccessibilityExposeDisplayNoneEnabled(enable);
-}
-
 void WebRuntimeFeatures::EnableAccessibilityExposeHTMLElement(bool enable) {
   RuntimeEnabledFeatures::SetAccessibilityExposeHTMLElementEnabled(enable);
 }
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-bfcache b/third_party/blink/web_tests/FlagExpectations/disable-bfcache
new file mode 100644
index 0000000..c8a2af0b
--- /dev/null
+++ b/third_party/blink/web_tests/FlagExpectations/disable-bfcache
@@ -0,0 +1,13 @@
+# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ]
+# tags: [ Release Debug ]
+# results: [ Timeout Crash Pass Failure Slow Skip ]
+
+# Following tests expect that back/forward cache is enabled.
+external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html [ Skip ]
+external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/bfcache-auto-attach.js [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/bfcache-document-updated.js [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/bfcache-request-basic.js [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features-same-site.js [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-blocklisted-features.js [ Skip ]
+virtual/bfcache/http/tests/inspector-protocol/bfcache/report-back-forward-cache-status-disabled-for-render-frame-host.js [ Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-back-forward-cache-same-site b/third_party/blink/web_tests/FlagExpectations/enable-back-forward-cache-same-site
deleted file mode 100644
index dcfa890..0000000
--- a/third_party/blink/web_tests/FlagExpectations/enable-back-forward-cache-same-site
+++ /dev/null
@@ -1,6 +0,0 @@
-# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ]
-# tags: [ Release Debug ]
-# results: [ Timeout Crash Pass Failure Slow Skip ]
-
-# TODO(peria): Make these tests work with same-site browsing instance swap.
-crbug.com/1136383 http/tests/inspector-protocol/network/interception-download.js [ Failure ]
diff --git a/third_party/blink/web_tests/FlagSpecificConfig b/third_party/blink/web_tests/FlagSpecificConfig
index cff0f35..80ce92a 100644
--- a/third_party/blink/web_tests/FlagSpecificConfig
+++ b/third_party/blink/web_tests/FlagSpecificConfig
@@ -12,8 +12,8 @@
     "args": ["--disable-site-isolation-trials"]
   },
   {
-    "name": "enable-back-forward-cache-same-site",
-    "args": ["--enable-features=BackForwardCache:enable_same_site/true"]
+    "name": "disable-bfcache",
+    "args": ["--disable-features=BackForwardCache"]
   },
   {
     "name": "enable-blink-heap-concurrent-marking",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a1119b39..fae954b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1604,6 +1604,14 @@
 virtual/layout_ng_grid_frag/external/wpt/css/css-break/grid/grid-item-fragmentation-041.html [ Pass ]
 virtual/layout_ng_grid_frag/external/wpt/css/css-break/grid/grid-item-fragmentation-042.html [ Pass ]
 
+### Tests failing with LayoutNGTableFragmentation enabled:
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/balance-table-with-border-spacing.html [ Failure ]
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/balance-table-with-fractional-height-row.html [ Failure ]
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/multicol-table-cell-height-002.xht [ Failure ]
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/multicol-table-cell-vertical-align-001.xht [ Failure ]
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/table-cell-content-change-000.html [ Failure ]
+crbug.com/1078927 virtual/layout_ng_table_frag/external/wpt/css/css-multicol/table/table-cell-content-change-001.html [ Failure ]
+
 ### With LayoutNGPrinting enabled:
 
 crbug.com/1121942 virtual/layout_ng_printing/printing/absolute-position-headers-and-footers.html [ Crash Failure ]
@@ -3198,6 +3206,8 @@
 crbug.com/626703 [ Linux ] external/wpt/url/failure.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac11-arm64 ] external/wpt/scroll-to-text-fragment/force-load-at-top.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/hidpi/device-pixel-ratio.https.html [ Failure ]
 crbug.com/626703 [ Mac10.14 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/hid.https.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-content/quotes-030.html [ Failure ]
 crbug.com/626703 [ Mac10.14 ] virtual/prerender/external/wpt/speculation-rules/prerender/fetch-blob.html [ Skip Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index ade0bb9..d47b7bd 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -275,6 +275,12 @@
     "args": ["--enable-blink-features=LayoutNGGridFragmentation"]
   },
   {
+    "prefix": "layout_ng_table_frag",
+    "bases": ["external/wpt/css/css-break/table",
+              "external/wpt/css/css-multicol/table"],
+    "args": ["--enable-blink-features=LayoutNGTableFragmentation"]
+  },
+  {
     "prefix": "layout_ng_printing",
     "bases": ["printing"],
     "args": ["--enable-blink-features=LayoutNGPrinting"]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations
index 9f3383c..67476842 100644
--- a/third_party/blink/web_tests/WebGPUExpectations
+++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -33,6 +33,12 @@
 wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:* [ Slow ]
 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:* [ Slow ]
 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:* [ Slow ]
+[ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:* [ Slow ]
+[ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:* [ Slow ]
+[ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:* [ Slow ]
+[ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:* [ Slow ]
+[ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:* [ Slow ]
+[ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:* [ Slow ]
 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:* [ Slow ]
 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,render_pass,storeOp:render_pass_store_op,color_attachment_only:* [ Slow ]
 # Intel only. Really slow and killed by the GPU watchdog?
@@ -99,18 +105,18 @@
 crbug.com/dawn/1003 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:util,texture,texel_data:unorm_texel_data_in_shader:format="rgb10a2unorm";* [ Failure ]
 crbug.com/dawn/1003 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="Sample";format="rg11b10ufloat";* [ Failure ]
 crbug.com/dawn/1003 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:readMethod="Sample";format="rgb9e5ufloat";* [ Failure ]
-crbug.com/dawn/1003 [ Linux ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgb9e5ufloat";* [ Failure ]
-crbug.com/dawn/1003 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgb9e5ufloat";* [ Failure ]
+crbug.com/dawn/1003 [ Linux ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb9e5ufloat";* [ Failure ]
+crbug.com/dawn/1003 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb9e5ufloat";* [ Failure ]
 crbug.com/tint/1228 [ Linux ] wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,builtin,abs:float_builtin_functions,abs_float:* [ Failure ]
 crbug.com/tint/1228 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,builtin,abs:float_builtin_functions,abs_float:* [ Failure ]
 
 # Precision. Only on Mac Intel
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8snorm";* [ Failure ]
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8snorm";* [ Failure ]
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8snorm";* [ Failure ]
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8snorm";* [ Failure ]
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8snorm";* [ Failure ]
-crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8snorm";* [ Failure ]
+crbug.com/dawn/1047 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8snorm";* [ Failure ]
 
 # Incorrect results, only on Mac Intel.
 crbug.com/dawn/1083 wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:format="depth32float";* [ Failure ]
@@ -131,6 +137,10 @@
 # Test shouldn't have a stencil8 variant.
 wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,depth_clip_clamp:depth_test_input_clamped:format="stencil8";* [ Failure ]
 
+# Failures because srgb-equality for compressed formats isn't implemented in Dawn validation.
+crbug.com/dawn/1204 [ Linux ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:* [ Crash ]
+crbug.com/dawn/1204 [ Linux ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:* [ Crash ]
+
 ###
 ### Test bugs (fixed upstream)
 ###
@@ -375,10 +385,10 @@
 crbug.com/dawn/704 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:offsets_and_sizes_copy_with_stencil_aspect:* [ Failure ]
 crbug.com/dawn/704 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:rowsPerImage_and_bytesPerRow_copy_with_stencil_aspect:* [ Failure ]
 
-crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8unorm";* [ Failure ]
-crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8unorm";* [ Failure ]
-crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8unorm";* [ Failure ]
-crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8unorm";* [ Failure ]
+crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8unorm";* [ Failure ]
+crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8unorm";* [ Failure ]
+crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8unorm";* [ Failure ]
+crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8unorm";* [ Failure ]
 crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";* [ Failure ]
 crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="rg8unorm";* [ Failure ]
 crbug.com/dawn/1071 [ Mac ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";* [ Failure ]
@@ -494,6 +504,14 @@
 # Handling of base_vertex base_instance is not implemented for indirect draws on D3D12.
 crbug.com/dawn/548 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,rendering,draw:arguments:indirect=true;* [ Failure ]
 
+# Device lost is triggered unexpectedly.
+crbug.com/dawn/1278 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,image_copy,texture_related:format:method="WriteTexture";depthOrArrayLayers=32;dimension="3d";format="r8unorm";mipLevel=2;copyWidthModifier=-1;copyHeightModifier=-1;copyDepthModifier=0;* [ Failure ]
+
+# (Intel-only) Wrong results in copyToTexture.
+crbug.com/dawn/1279 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";width=256;height=255;* [ Failure ]
+crbug.com/dawn/1279 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";width=256;height=255;* [ Failure ]
+crbug.com/dawn/1279 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";width=256;height=255;* [ Failure ]
+
 # (Intel-only) StoreOpClear handling is overclearing resources that should be preserved
 crbug.com/1237175 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";format="rg32float";uninitializeMethod="StoreOpClear";canaryOnCreation=true;* [ Failure ]
 crbug.com/1237175 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";format="rgba32float";uninitializeMethod="StoreOpClear";canaryOnCreation=true;* [ Failure ]
@@ -508,18 +526,18 @@
 crbug.com/dawn/1063 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,render_pipeline,pipeline_output_targets:color,component_count,blend:* [ Failure ]
 
 # (Intel-only?) Test failures on Mac 11.5.2
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r32float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg11b10ufloat";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg16float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg32float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba16float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba32float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r32float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg11b10ufloat";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg16float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg32float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba16float";* [ Failure ]
-crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg11b10ufloat";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg11b10ufloat";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16float";* [ Failure ]
+crbug.com/dawn/1107 [ Mac11 ] wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32float";* [ Failure ]
 
 # (Intel-only?) Flaky test failures on Mac 11.5.2
 crbug.com/dawn/1119 [ Mac11 ] wpt_internal/webgpu/cts.https.html?worker=1&q=webgpu:api,operation,rendering,basic:large_draw:* [ RetryOnFailure ]
@@ -540,3 +558,4 @@
 
 # KI due to support in Tint being rolled back
 crbug.com/tint/1322 [ Win ] wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,sampling,gradients_in_varying_loop:derivative_in_varying_loop:* [ Failure ]
+
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index c938ba5..4e3fdee 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: 0e8780877c5e75d6943ce560e91742b51829382b
+Version: 95d612c563e75ef0b919a2f18d19976a9c82c073
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index cf278bff..1c5912f1 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -233637,7 +233637,7 @@
      []
     ],
     "access-control-expose-headers-parsing.window-expected.txt": [
-     "3000d57c8a13cceb01307f38d858245617fb50aa",
+     "0fe27f2fdca8ae7eeb0f92e9bef2717a6d8ac1d1",
      []
     ],
     "resources": {
@@ -233650,7 +233650,7 @@
       []
      ],
      "access-control-expose-headers.json": [
-      "4ab38fbe09b7a3e8e648dcd0988706512429497c",
+      "e8915f7ffe1533eb9b00292552ea216cc818c0ca",
       []
      ],
      "cache-304.py": [
@@ -285790,7 +285790,7 @@
         ]
        },
        "events-expected.txt": [
-        "6dad05534728dc6a05db46b5c112a2fd9546e8ce",
+        "b8ce62d7455e3811966bd3053e501818bc290286",
         []
        ],
        "resources": {
@@ -289778,7 +289778,7 @@
       []
      ],
      "dedicated-worker.https-expected.txt": [
-      "883c29a04dfcd6030c7bf83b60deb63e970cd110",
+      "cc01f8a1e618b22c9a3f0f2dd80d1dd665944380",
       []
      ],
      "javascript.https.html.headers": [
@@ -289928,6 +289928,10 @@
        "d0e547b130db1307fe81589f7a2e3706fc1e65ab",
        []
       ],
+      "fetch-and-create-url.html": [
+       "6b0f96221dc47c367a53ffac3b07276070f71892",
+       []
+      ],
       "fetch-in-dedicated-worker.js": [
        "bd60d07952ccbf2f4c6954ce65083ce0eada13f4",
        []
@@ -290047,6 +290051,10 @@
       "worker-owner.js": [
        "d1f172a0b87c73d3591345c9b232bf40b7656eed",
        []
+      ],
+      "worker-support.js": [
+       "860ee6826c2029260c5007f475fcc9368abf5de2",
+       []
       ]
      },
      "sandbox.https.html.headers": [
@@ -290054,7 +290062,7 @@
       []
      ],
      "shared-workers.https-expected.txt": [
-      "f3e13f6fe8eb2fb2737acb85d635f154b04264e1",
+      "8d12b4d8d6918bbacd7677d55ac553f303ceea3f",
       []
      ],
      "srcdoc.https.html.headers": [
@@ -290244,7 +290252,7 @@
       },
       "navigation-reporting": {
        "report-only-four-reports.https.html.sub.headers": [
-        "9e864109a1e6218f0f91ef85245e52590d1407ad",
+        "50c3045bb64214d2a4b03817661a7446cf56836f",
         []
        ],
        "report-only-from-unsafe-none.https.html.headers": [
@@ -290252,7 +290260,7 @@
         []
        ],
        "report-only-same-origin-report-to.https.html.sub.headers": [
-        "97104b6d6cfbd8065d3fb820183434cee1704609",
+        "04bc49906b535339cc25f11793f9b0b51421a4f9",
         []
        ],
        "report-only-same-origin-with-coep-report-only.https.html.headers": [
@@ -290268,19 +290276,19 @@
         []
        ],
        "reporting-coop-navigated-popup.https.html.sub.headers": [
-        "795e7891cb1986dff28ba453298057d2bd0153e5",
+        "a6a27c2d3e52aac14b0d7bd65bf62787cffe9931",
         []
        ],
        "reporting-popup-same-origin-allow-popups-report-to.https.html.sub.headers": [
-        "50d1e34efc224071a093fc9718a3aa864805c798",
+        "3e213a95a3257e07c841111cfa6abdfe41457182",
         []
        ],
        "reporting-popup-same-origin-coep-report-to.https.html.sub.headers": [
-        "a978bd3e00766a1b84b1c7a306721a12576d0c4b",
+        "0f78bdb2d09d602c89cf2e26fd9fbf592cbec91a",
         []
        ],
        "reporting-popup-same-origin-report-to.https.html.sub.headers": [
-        "200360e3c97acdad37641d49beddc1550277a9a0",
+        "79c851a86c658568bc8de11406e9656a11cb0a87",
         []
        ],
        "reporting-popup-same-origin.https.html.headers": [
@@ -290288,7 +290296,7 @@
         []
        ],
        "reporting-popup-unsafe-none-report-to.https.html.sub.headers": [
-        "f22298ef94ce55884b14e163b4bfa10871a9a1d1",
+        "f1f18d67080f819ec55e3abf0316cafe1d756ef0",
         []
        ]
       },
@@ -310371,6 +310379,10 @@
       "beb12f5da551780fcb4378bef4661b9699a5d009",
       []
      ],
+     "shared-worker.js": [
+      "f3ef3feb964cb73784c8ec2e31505dfc7aa67a62",
+      []
+     ],
      "sizes-helper.js": [
       "86336686b32902ec1c123b0f55ff67e9aba43062",
       []
@@ -372449,6 +372461,13 @@
        {}
       ]
      ],
+     "scroll-target-margin-006.html": [
+      "48e246249f110612a71e201b461b3155a1026bb1",
+      [
+       null,
+       {}
+      ]
+     ],
      "scrollTo-scrollBy-snaps.html": [
       "6013de50441dfb0b6f4d6af5082eaa1abf64711c",
       [
@@ -445316,7 +445335,7 @@
       ]
      ],
      "dedicated-worker.https.html": [
-      "cc0c470910bc1915aa0ddb0ae136f0d8579044e6",
+      "1ba624181cb7c23ab0ac61a6b9fa1841d4575710",
       [
        null,
        {}
@@ -445548,7 +445567,7 @@
       ]
      ],
      "shared-workers.https.html": [
-      "82b5e505af13fb5e5826cce4e88689f17939d6c0",
+      "2558f2dd0b40ab8233d6dad58a246210569ef6d9",
       [
        null,
        {}
@@ -473140,7 +473159,7 @@
      ]
     ],
     "MediaStreamTrack-transfer.https.html": [
-     "f0fcdaf529cd1660d2e18f6746d16a722be05564",
+     "9d582f3d9be259ad481133ca1ff6fd2fe2448d6e",
      [
       null,
       {
@@ -496091,6 +496110,13 @@
       {}
      ]
     ],
+    "shared-worker-rt-entry.html": [
+     "194500a09503a46f454d879ec984be0c83dd2bb9",
+     [
+      null,
+      {}
+     ]
+    ],
     "sizes-cache.any.js": [
      "af70e5a6ded3e63d158fd929feacf0827b3cafc9",
      [
@@ -544785,6 +544811,13 @@
       }
      ]
     ],
+    "datagram-cancel-crash.https.window.js": [
+     "fae613e2138cc6cf1437024a9f32d155fd053793",
+     [
+      "webtransport/datagram-cancel-crash.https.window.html",
+      {}
+     ]
+    ],
     "datagrams.https.any.js": [
      "401154e1878c32e8a0110c7834ab3817dc78631a",
      [
diff --git a/third_party/blink/web_tests/external/wpt/cors/access-control-expose-headers-parsing.window-expected.txt b/third_party/blink/web_tests/external/wpt/cors/access-control-expose-headers-parsing.window-expected.txt
index 3000d57..0fe27f2f 100644
--- a/third_party/blink/web_tests/external/wpt/cors/access-control-expose-headers-parsing.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/cors/access-control-expose-headers-parsing.window-expected.txt
@@ -8,7 +8,7 @@
 PASS Parsing: Access-Control-Expose-Headers%3A%20bb-8%0D%0AAccess-Control-Expose-Headers%3A%20no%20no
 PASS Parsing: Access-Control-Expose-Headers%3A%20no%0D%0AAccess-Control-Expose-Headers%3A%20bb-8
 FAIL Parsing: Access-Control-Expose-Headers%3A%0D%0AAccess-Control-Expose-Headers%3A%20bb-8 assert_equals: expected (string) "hey" but got (object) null
-PASS Parsing: Access-Control-Expose-Headers%3A%20%2Cbb-8
+FAIL Parsing: Access-Control-Expose-Headers%3A%20%2Cbb-8 assert_equals: expected (string) "hey" but got (object) null
 PASS Parsing: Access-Control-Expose-Headers%3A%20bb-8%0C
 PASS Parsing: Access-Control-Expose-Headers%3A%20bb-8%0B
 PASS Parsing: Access-Control-Expose-Headers%3A%20bb-8%0B%2Cbb-8
diff --git a/third_party/blink/web_tests/external/wpt/cors/resources/access-control-expose-headers.json b/third_party/blink/web_tests/external/wpt/cors/resources/access-control-expose-headers.json
index 4ab38fb..e8915f7 100644
--- a/third_party/blink/web_tests/external/wpt/cors/resources/access-control-expose-headers.json
+++ b/third_party/blink/web_tests/external/wpt/cors/resources/access-control-expose-headers.json
@@ -33,7 +33,7 @@
   },
   {
     "input": "Access-Control-Expose-Headers: ,bb-8",
-    "exposed": false
+    "exposed": true
   },
   {
     "input": "Access-Control-Expose-Headers: bb-8\u000C",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-target-margin-006.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-target-margin-006.html
new file mode 100644
index 0000000..48e2462
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-target-margin-006.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<title>scrollIntoView() and scroll-margin applied to an inline element</title>
+<link rel='author' title='Martin Robinson' href='http://igalia.com'>
+<link rel='help' href='https://www.w3.org/TR/css-scroll-snap-1/#scroll-margin'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style type='text/css'>
+  .container {
+    border: solid black 1px;
+    height: 40px;
+    width: 40px;
+    overflow: auto;
+  }
+</style>
+
+<div class="container">
+  <div style="height: 1000px; width: 2000px;"></div>
+  <div style="width: 2000px;">
+    <span>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</span>
+    <span id="target">TARGETTARGETTARGETTARGET</span>
+    <span>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</span>
+  </div>
+  <div style="height: 1000px; width: 2000px;"></div>
+</div>
+
+<script>
+
+test(() => {
+  target.scrollIntoView();
+  const scroller = target.parentElement.parentElement;
+  let expectedScrollPosition = [scroller.scrollLeft - 20, scroller.scrollTop - 20];
+  scroller.scrollTo(0, 0);
+
+  target.style.scrollMarginTop = "20px";
+  target.style.scrollMarginLeft = "20px";
+  target.scrollIntoView();
+  assert_equals(scroller.scrollLeft, expectedScrollPosition[0]);
+  assert_equals(scroller.scrollTop, expectedScrollPosition[1]);
+
+  target.style.scrollMarginTop = "0px";
+  target.style.scrollMarginLeft = "0px";
+
+  scroller.scrollTo(2000, 2000);
+  target.scrollIntoView({"block": "end", "inline": "end"});
+  expectedScrollPosition = [scroller.scrollLeft + 20, scroller.scrollTop + 20];
+  scroller.scrollTo(2000, 2000);
+
+  target.style.scrollMarginBottom = "20px";
+  target.style.scrollMarginRight = "20px";
+  target.scrollIntoView({"block": "end", "inline": "end"});
+  assert_equals(scroller.scrollLeft, expectedScrollPosition[0]);
+  assert_equals(scroller.scrollTop, expectedScrollPosition[1]);
+
+}, "scroll-margin is taken into account when scrolling an inline element into view");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt
index 4ea413e..4595be0 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt
@@ -8,8 +8,10 @@
 PASS public to private: failed preflight.
 PASS public to private: success.
 PASS public to public: success.
-FAIL treat-as-public to local: failure. assert_equals: fetch error expected (string) "TypeError" but got (undefined) undefined
-PASS treat-as-public to private: failure.
+FAIL treat-as-public to local: failed preflight. assert_equals: fetch error expected (string) "TypeError" but got (undefined) undefined
+FAIL treat-as-public to local: success. assert_equals: response status expected 200 but got 405
+FAIL treat-as-public to private: failed preflight. assert_equals: fetch error expected (string) "TypeError" but got (undefined) undefined
+FAIL treat-as-public to private: success. assert_equals: fetch error expected (undefined) undefined but got (string) "TypeError"
 PASS treat-as-public to public: success.
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window.js
index 528b556a..7ca0b43 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.https.window.js
@@ -95,12 +95,33 @@
     server: Server.HTTPS_LOCAL,
     treatAsPublic: true,
   },
+  target: { server: Server.HTTPS_LOCAL },
+  expected: WorkerFetchTestResult.FAILURE,
+}), "treat-as-public to local: failed preflight.");
+
+promise_test(t => workerFetchTest(t, {
+  source: {
+    server: Server.HTTPS_LOCAL,
+    treatAsPublic: true,
+  },
   target: {
     server: Server.HTTPS_LOCAL,
     behavior: { preflight: PreflightBehavior.success(token()) },
   },
+  expected: WorkerFetchTestResult.SUCCESS,
+}), "treat-as-public to local: success.");
+
+promise_test(t => workerFetchTest(t, {
+  source: {
+    server: Server.HTTPS_LOCAL,
+    treatAsPublic: true,
+  },
+  target: {
+    server: Server.HTTPS_PRIVATE,
+    behavior: { response: ResponseBehavior.allowCrossOrigin() },
+  },
   expected: WorkerFetchTestResult.FAILURE,
-}), "treat-as-public to local: failure.");
+}), "treat-as-public to private: failed preflight.");
 
 promise_test(t => workerFetchTest(t, {
   source: {
@@ -114,8 +135,8 @@
       response: ResponseBehavior.allowCrossOrigin(),
     },
   },
-  expected: WorkerFetchTestResult.FAILURE,
-}), "treat-as-public to private: failure.");
+  expected: WorkerFetchTestResult.SUCCESS,
+}), "treat-as-public to private: success.");
 
 promise_test(t => workerFetchTest(t, {
   source: {
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt
index cd62872..6deb19b 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt
@@ -9,7 +9,7 @@
 PASS treat-as-public to private: failure.
 PASS treat-as-public to public: success.
 PASS private https to local: failure.
-PASS pubiic https to local: failure.
+PASS public https to private: failure.
 PASS public https to local: failure.
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window.js
index 77be8bb9..cf6e1ca 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/worker-fetch.window.js
@@ -120,14 +120,14 @@
 promise_test(t => workerFetchTest(t, {
   source: { server: Server.HTTPS_PUBLIC },
   target: {
-    server: Server.HTTP_LOCAL,
+    server: Server.HTTP_PRIVATE,
     behavior: {
       preflight: PreflightBehavior.success(token()),
       response: ResponseBehavior.allowCrossOrigin(),
     },
   },
   expected: WorkerFetchTestResult.FAILURE,
-}), "pubiic https to local: failure.");
+}), "public https to private: failure.");
 
 promise_test(t => workerFetchTest(t, {
   source: { server: Server.HTTPS_PUBLIC },
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
index 6dad055..b8ce62d74 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
@@ -1,6 +1,6 @@
 This is a testharness.js-based test.
-NOTRUN SameOrigin Should be BFCached but actually wasn't
-NOTRUN SameSite Should be BFCached but actually wasn't
+PASS SameOrigin
+PASS SameSite
 PASS CrossSite
 PASS beforeunload
 NOTRUN unload Should be BFCached but actually wasn't
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
index 883c29a..cc01f8a1 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
@@ -7,5 +7,11 @@
 PASS COEP: none module worker in COEP: require-corp frame
 FAIL COEP: require-corp module worker in COEP: none frame assert_equals: expected "FAILED" but got "LOADED"
 PASS COEP: require-corp module worker in COEP: require-corp frame
+PASS COEP: worker inherits COEP for blob URL.
+FAIL COEP: worker inherits COEP from blob URL creator, not owner. assert_equals: expected "FAILED" but got "LOADED"
+PASS COEP: worker inherits COEP for data URL.
+PASS COEP: worker inherits COEP from owner, not data URL creator.
+FAIL COEP: worker inherits COEP for filesystem URL. assert_unreached: Worker.onerror should not be called Reached unreachable code
+FAIL COEP: worker inherits COEP from filesystem URL creator, not owner. assert_equals: expected "FAILED" but got "LOADED"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https.html
index cc0c470..1ba6241 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https.html
@@ -3,110 +3,212 @@
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src="/common/get-host-info.sub.js"></script>
+<script src="resources/worker-support.js"></script>
 <body>
 <script>
-const HOST = get_host_info();
-const FETCH_URL = `${HOST.REMOTE_ORIGIN}/common/blank.html`;
-const WORKER_URL = new URL('resources/dedicated-worker.js', location).href;
-const WITH_COEP = '?pipe=header(cross-origin-embedder-policy,require-corp)';
 
-async function createWorker(t, frameHasCoep, workerHasCoep, workerOptions) {
-  const frame = document.createElement("iframe");
-  t.add_cleanup(() => frame.remove());
-  frame.src = '/common/blank.html';
-  if (frameHasCoep) {
-    frame.src += WITH_COEP;
-  }
-  document.body.append(frame);
+const targetUrl = resolveUrl("/common/blank.html", {
+    host: get_host_info().REMOTE_HOST,
+}).href;
 
-  await new Promise(resolve => {
-    frame.addEventListener('load', resolve, {once: true})
-  });
-  const worker = new frame.contentWindow.Worker(
-    workerHasCoep ? WORKER_URL + WITH_COEP : WORKER_URL, workerOptions);
-
-  return worker;
+function workerUrl(options) {
+  return resolveUrl("resources/dedicated-worker.js", options);
 }
 
-function waitForMessage(target) {
-  return new Promise(resolve => {
-    target.addEventListener('message', resolve, {once: true});
+async function createWorker(t, url, options) {
+  const { ownerCoep, workerOptions } = options || {};
+
+  const frameUrl = resolveUrl("/common/blank.html", {
+    coep: ownerCoep,
   });
+  const frame = await withIframe(t, frameUrl);
+
+  return new frame.contentWindow.Worker(url, workerOptions);
 }
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, false, {});
+  const worker = await createWorker(t, workerUrl());
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'LOADED');
 }, 'COEP: none worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, false, {});
+  const worker = await createWorker(t, workerUrl(), {
+    ownerCoep: "require-corp",
+  });
   await new Promise(resolve => {
     worker.onerror = resolve;
   });
 }, 'COEP: none worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, true, {});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }));
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, true, {});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    ownerCoep: "require-corp",
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, false, {type: 'module'});
+  const worker = await createWorker(t, workerUrl(), {
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'LOADED');
 }, 'COEP: none module worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, false, {type: 'module'});
+  const worker = await createWorker(t, workerUrl(), {
+    ownerCoep: "require-corp",
+    workerOptions: { type: 'module' },
+  });
   await new Promise(resolve => {
     worker.onerror = resolve;
   });
 }, 'COEP: none module worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, true, {type: 'module'});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp module worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, true, {type: 'module'});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    ownerCoep: "require-corp",
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp module worker in COEP: require-corp frame');
 
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for blob URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP from blob URL creator, not owner.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for data URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'LOADED');
+}, "COEP: worker inherits COEP from owner, not data URL creator.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for filesystem URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP from filesystem URL creator, not owner.");
+
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html
new file mode 100644
index 0000000..6b0f962
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Fetch and create Blob</title>
+<script>
+  async function responseToBlob(response) {
+    let blob;
+    try {
+      blob = await response.blob();
+    } catch (e) {
+      return { error: `blob error: ${e.name}` };
+    }
+
+    return { url: URL.createObjectURL(blob) };
+  }
+
+  async function responseToData(response) {
+    const mimeType = response.headers.get("content-type");
+
+    let text;
+    try {
+      text = await response.text();
+    } catch(e) {
+      return { error: `text error: ${e.name}` };
+    }
+
+    return { url: `data:${mimeType},${encodeURIComponent(text)}` };
+  }
+
+  async function responseToFilesystem(response) {
+    if (!window.webkitRequestFileSystem) {
+      return { error: "unimplemented" };
+    }
+
+    let blob;
+    try {
+      blob = await response.blob();
+    } catch (e) {
+      return { error: `blob error: ${e.name}` };
+    }
+
+    const fs = await new Promise(resolve => {
+      window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, resolve);
+    });
+
+    const file = await new Promise(resolve => {
+      fs.root.getFile('fetch-and-create-url', { create: true }, resolve);
+    });
+
+    const writer = await new Promise(resolve => file.createWriter(resolve));
+
+    try {
+      await new Promise((resolve, reject) => {
+        writer.onwriteend = resolve;
+        writer.onerror = reject;
+        writer.write(blob);
+      });
+    } catch (e) {
+      return { error: `file write error: ${e.name}` };
+    }
+
+    return { url: file.toURL() };
+  }
+
+  async function responseToScheme(response, scheme) {
+    switch (scheme) {
+      case "blob":
+        return responseToBlob(response);
+      case "data":
+        return responseToData(response);
+      case "filesystem":
+        return responseToFilesystem(response);
+      default:
+        return { error: `unknown scheme: ${scheme}` };
+    }
+  }
+
+  async function fetchToScheme(url, scheme) {
+    let response;
+    try {
+      response = await fetch(url);
+    } catch (e) {
+      return { error: `fetch error: ${e.name}` };
+    }
+
+    return responseToScheme(response, scheme);
+  }
+
+  const params = new URL(window.location).searchParams;
+  fetchToScheme(params.get("url"), params.get("scheme"))
+    .then((message) => { parent.postMessage(message, "*"); });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/worker-support.js b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/worker-support.js
new file mode 100644
index 0000000..860ee68
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/resources/worker-support.js
@@ -0,0 +1,81 @@
+// Configures `url` such that the response carries a `COEP: ${value}` header.
+//
+// `url` must be a `URL` instance.
+function setCoep(url, value) {
+  url.searchParams
+      .set("pipe", `header(cross-origin-embedder-policy,${value})`);
+}
+
+// Resolves the given `relativeUrl` relative to the current window's location.
+//
+// `options` can contain the following keys:
+//
+// - `coep`: value passed to `setCoep()`, if present.
+// - `host`: overrides the host of the returned URL.
+//
+// Returns a `URL` instance.
+function resolveUrl(relativeUrl, options) {
+  const url = new URL(relativeUrl, window.location);
+
+  if (options !== undefined) {
+    const { coep, host } = options;
+    if (coep !== undefined) {
+      setCoep(url, coep);
+    }
+    if (host !== undefined) {
+      url.host = host;
+    }
+  }
+
+  return url;
+}
+
+// Adds an iframe loaded from `url` to the current document, waiting for it to
+// load before returning.
+//
+// The returned iframe is removed from the document at the end of the test `t`.
+async function withIframe(t, url) {
+  const frame = document.createElement("iframe");
+  frame.src = url;
+
+  t.add_cleanup(() => frame.remove());
+
+  const loadedPromise = new Promise(resolve => {
+    frame.addEventListener('load', resolve, {once: true});
+  });
+  document.body.append(frame);
+  await loadedPromise;
+
+  return frame;
+}
+
+// Asynchronously waits for a single "message" event on the given `target`.
+function waitForMessage(target) {
+  return new Promise(resolve => {
+    target.addEventListener('message', resolve, {once: true});
+  });
+}
+
+// Fetches `url` from a document with COEP `creatorCoep`, then serializes it
+// and returns a URL pointing to the fetched body with the given `scheme`.
+//
+// - `creatorCoep` is passed to `setCoep()`.
+// - `scheme` may be one of: "blob", "data" or "filesystem".
+//
+// The returned URL is valid until the end of the test `t`.
+async function createLocalUrl(t, { url, creatorCoep, scheme }) {
+  const frameUrl = resolveUrl("resources/fetch-and-create-url.html", {
+    coep: creatorCoep,
+  });
+  frameUrl.searchParams.set("url", url);
+  frameUrl.searchParams.set("scheme", scheme);
+
+  const messagePromise = waitForMessage(window);
+  const frame = await withIframe(t, frameUrl);
+
+  const evt = await messagePromise;
+  const message = evt.data;
+  assert_equals(message.error, undefined, "url creation error");
+
+  return message.url;
+}
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https-expected.txt
index f3e13f6..8d12b4d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https-expected.txt
@@ -2,8 +2,13 @@
 PASS default policy (derived from response)
 PASS "require-corp" (derived from response)
 PASS default policy (derived from owner set due to use of local scheme - blob URL)
+FAIL require-corp (derived from blob URL creator) assert_equals: expected "failure" but got "success"
 FAIL "require-corp" (derived from owner set due to use of local scheme - blob URL) assert_equals: expected "failure" but got "success"
 PASS default policy (derived from owner set due to use of local scheme - data URL)
+PASS default policy (not derived from data URL creator)
 FAIL "require-corp" (derived from owner set due to use of local scheme - data URL) assert_equals: expected "failure" but got "success"
+FAIL default policy (derived from owner set due to use of local scheme - filesystem URL) assert_unreached: SharedWorker.onerror should not be called Reached unreachable code
+FAIL require-corp (derived from filesystem URL creator) assert_unreached: SharedWorker.onerror should not be called Reached unreachable code
+FAIL "require-corp" (derived from owner set due to use of local scheme - filesystem URL) assert_unreached: SharedWorker.onerror should not be called Reached unreachable code
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https.html
index 82b5e505a..2558f2dd 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/shared-workers.https.html
@@ -5,6 +5,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
+<script src="resources/worker-support.js"></script>
 <body>
 <p>Verify the Cross-Origin Embedder Policy for Shared Workers by performing a
 cross-domain "fetch" request for a resource that does not specify a COEP. Only
@@ -13,51 +14,39 @@
 <script>
 'use strict';
 
-const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
-const BASE = new URL("resources", location).pathname
-const testUrl = `${REMOTE_ORIGIN}${BASE}/empty-coep.py`;
-const workerHttpUrl = `${ORIGIN}${BASE}/shared-worker-fetch.js.py`;
-let workerBlobUrl;
-let workerDataUrl;
+const testUrl = resolveUrl("resources/empty-coep.py", {
+  host: get_host_info().REMOTE_HOST,
+}).href;
 
-promise_setup(() => {
-  return fetch(workerHttpUrl)
-    .then((response) => response.text())
-    .then((text) => {
-      workerDataUrl = 'data:text/javascript;base64,' + btoa(text);
-      workerBlobUrl = URL.createObjectURL(
-        new Blob([text], { 'Content-Type': 'text/javascript' })
-      );
-    });
-});
+function makeWorkerUrl(options) {
+  return resolveUrl("resources/shared-worker-fetch.js.py", options);
+}
 
 /**
  * Create a Shared Worker within an iframe
  *
  * @param {object} t - a testharness.js subtest instance (used to reset global
  *                     state)
- * @param {string} ownerCoep - the Cross-Origin Embedder Policy of the iframe
- * @param {string} workerUrl - the URL from which the Shared Worker should be
- *                             created
+ * @param {string} url - the URL from which the Shared Worker should be
+ *                       created
+ * @param {string} options.ownerCoep - the Cross-Origin Embedder Policy of the
+                                       iframe
  */
-function create(t, ownerCoep, workerUrl) {
-  const iframe = document.createElement('iframe');
-  iframe.src = 'resources/empty-coep.py' +
-    (ownerCoep ? '?value=' + ownerCoep : '');
+async function createWorker(t, url, options) {
+  const { ownerCoep } = options || {};
+  const frameUrl = resolveUrl("/common/blank.html", { coep: ownerCoep });
 
-  return new Promise((resolve, reject) => {
-      document.body.appendChild(iframe);
-      t.add_cleanup(() => iframe.remove());
-      iframe.onload = () => resolve(iframe);
-    })
-    .then((iframe) => {
-      const sw = new iframe.contentWindow.SharedWorker(workerUrl);
+  const iframe = await withIframe(t, frameUrl);
 
-      return new Promise((resolve) => {
-        sw.port.addEventListener('message', () => resolve(sw), { once: true });
-        sw.port.start();
-      });
-    });
+  const sw = new iframe.contentWindow.SharedWorker(url);
+  sw.onerror = t.unreached_func('SharedWorker.onerror should not be called');
+
+  await new Promise((resolve) => {
+    sw.port.addEventListener('message', resolve, { once: true });
+    sw.port.start();
+  });
+
+  return sw;
 }
 
 /**
@@ -76,57 +65,164 @@
   });
 };
 
-promise_test((t) => {
-  return create(t, null, workerHttpUrl)
-    .then((worker) => fetchFromWorker(worker, testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const worker = await createWorker(t, makeWorkerUrl());
+  const result = await fetchFromWorker(worker, testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from response)');
 
-promise_test((t) => {
-  return create(t, null, workerHttpUrl + '?value=require-corp')
-    .then((worker) => fetchFromWorker(worker, testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const worker = await createWorker(t, makeWorkerUrl({ coep: 'require-corp' }));
+  const result = await fetchFromWorker(worker, testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from response)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerBlobUrl),
-      create(t, null, workerBlobUrl),
-      create(t, null, workerBlobUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from owner set due to use of local scheme - blob URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerBlobUrl),
-      create(t, 'require-corp', workerBlobUrl),
-      create(t, null, workerBlobUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, 'require-corp (derived from blob URL creator)');
+
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl, { ownerCoep: 'require-corp' }),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from owner set due to use of local scheme - blob URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerDataUrl),
-      create(t, null, workerDataUrl),
-      create(t, null, workerDataUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from owner set due to use of local scheme - data URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerDataUrl),
-      create(t, 'require-corp', workerDataUrl),
-      create(t, null, workerDataUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
+}, 'default policy (not derived from data URL creator)');
+
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl, { ownercoep: 'require-corp' }),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from owner set due to use of local scheme - data URL)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
+}, 'default policy (derived from owner set due to use of local scheme - filesystem URL)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, 'require-corp (derived from filesystem URL creator)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl, { ownerCoep: 'require-corp' }),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, '"require-corp" (derived from owner set due to use of local scheme - filesystem URL)');
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/inert/inert-node-is-uneditable.tentative.html b/third_party/blink/web_tests/external/wpt/inert/inert-node-is-uneditable.tentative.html
index 6da2379..23182b9 100644
--- a/third_party/blink/web_tests/external/wpt/inert/inert-node-is-uneditable.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/inert/inert-node-is-uneditable.tentative.html
@@ -16,11 +16,15 @@
 var notEditable = document.querySelector('#not-editable');
 var editable = document.querySelector('#editable');
 
-promise_test(async () => {
+promise_test(async function() {
     notEditable.focus();
     var oldValue = notEditable.textContent;
     assert_equals(oldValue, "I'm not editable.");
-    await test_driver.send_keys(document.body, 'a');
+    await promise_rejects_js(
+        this,
+        Error,
+        test_driver.send_keys(notEditable, 'a'),
+        "send_keys should reject for non-interactive elements");
     assert_equals(notEditable.textContent, oldValue);
 }, "Can't edit inert contenteditable");
 
@@ -28,7 +32,7 @@
     editable.focus();
     var oldValue = editable.textContent;
     assert_equals(oldValue, "I'm editable.");
-    await test_driver.send_keys(document.body, 'a');
+    await test_driver.send_keys(editable, 'a');
     assert_not_equals(editable.textContent, oldValue);
 }, "Can edit non-inert contenteditable");
 
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https.html
index f0fcdaf5..9d582f3 100644
--- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https.html
+++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https.html
@@ -6,19 +6,37 @@
 <script src=/resources/testdriver-vendor.js></script>
 <script src=permission-helper.js></script>
 <script id="workerCode" type="javascript/worker">
-self.onmessage = (track) => {}
+self.onmessage = (e) => {
+  if(e.data instanceof MediaStreamTrack) {
+    self.postMessage({result: 'Success'});
+  } else {
+    self.postMessage({
+      result: 'Failure',
+      error: `${e.data} is not a MediaStreamTrack`
+    });
+  }
+}
 </script>
 <script>
 promise_test(async () => {
-    const workerBlob = new Blob([document.querySelector('#workerCode').textContent],
-                               {type: "text/javascript"});
-    const workerUrl = window.URL.createObjectURL(workerBlob);
-    const worker = new Worker(workerUrl);
-    window.URL.revokeObjectURL(workerUrl);
-
-    await setMediaPermission("granted", ["camera"]);
-    const stream = await navigator.mediaDevices.getUserMedia({video: true});
-    const track = stream.getVideoTracks()[0];
-    worker.postMessage(track, [track]);
+  const workerBlob = new Blob([document.querySelector('#workerCode').textContent],
+                {type: "text/javascript"});
+  const workerUrl = window.URL.createObjectURL(workerBlob);
+  const worker = new Worker(workerUrl);
+  window.URL.revokeObjectURL(workerUrl);
+  await setMediaPermission("granted", ["camera"]);
+  const stream = await navigator.mediaDevices.getUserMedia({video: true});
+  const track = stream.getVideoTracks()[0];
+  const result = new Promise((resolve, reject) => {
+    worker.onmessage = (e) => {
+      if (e.data.result === 'Failure') {
+        reject('Failed: ' + e.data.error);
+      } else {
+        resolve();
+      }
+    };
+  });
+  worker.postMessage(track, [track]);
+  return result;
 });
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/shared-worker.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/shared-worker.js
new file mode 100644
index 0000000..f3ef3feb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/shared-worker.js
@@ -0,0 +1,3 @@
+self.onconnect = e => {
+  e.ports[0].postMessage(performance.timeOrigin);
+}
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/shared-worker-rt-entry.html b/third_party/blink/web_tests/external/wpt/resource-timing/shared-worker-rt-entry.html
new file mode 100644
index 0000000..194500a09
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/shared-worker-rt-entry.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>Resource Timing Entry for Shared Workers</title>
+<link rel="help" href="https://w3c.github.io/resource-timing/"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+</head>
+<body>
+<script>
+    promise_test(async () => {
+        const url = new URL(`resources/shared-worker.js?${token()}`, location.href).toString();
+        const worker = new SharedWorker(url, 'name');
+        const {data} = await new Promise(resolve => {
+            worker.port.onmessage = resolve;
+        });
+
+        const timeOrigin = data;
+        const entries = performance.getEntriesByName(url);
+        assert_equals(entries.length, 0, "SharedWorker should not create a ResourceTiming entry");
+    }, "Shared workers should not generate Resource Timing Entries");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html
new file mode 100644
index 0000000..2948d6b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Animating marquee's parent inside display:none</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations-1/">
+<link rel="help" href="https://crbug.com/1290016">
+<div id=container></div>
+<script>
+  let outer = document.createElement('div');
+  outer.style.display = 'none';
+  let inner = document.createElement('div');
+  let marquee = document.createElement('marquee');
+
+  let effect = new KeyframeEffect(inner, [{'width': '1px'}], 1);
+  let anim = new Animation(effect, null);
+  anim.pause();
+
+  document.body.append(outer);
+  outer.append(inner);
+  inner.append(marquee);
+
+  // Don't crash.
+</script>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt
index 6d18abcb2c..9185be8 100644
--- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt
@@ -4,9 +4,6 @@
 
 CONSOLE ERROR: The Content-Security-Policy directive 'script-src' contains the keyword 'none' alongside with other source expressions. The keyword 'none' must be the only source expression in the directive value, otherwise it is ignored.
 CONSOLE ERROR: The Content-Security-Policy directive 'script-src' contains the keyword 'none' alongside with other source expressions. The keyword 'none' must be the only source expression in the directive value, otherwise it is ignored.
-CONSOLE ERROR: The Content-Security-Policy directive 'script-src' contains the keyword 'none' alongside with other source expressions. The keyword 'none' must be the only source expression in the directive value, otherwise it is ignored.
-CONSOLE ERROR: The Content-Security-Policy directive 'script-src' contains the keyword 'none' alongside with other source expressions. The keyword 'none' must be the only source expression in the directive value, otherwise it is ignored.
-CONSOLE ERROR: The Content-Security-Policy directive 'script-src' contains the keyword 'none' alongside with other source expressions. The keyword 'none' must be the only source expression in the directive value, otherwise it is ignored.
 CONSOLE ERROR: Refused to load the script 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script.js' because it violates the following Content Security Policy directive: "script-src 'none' 'none' 'none'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
 
 'none' should be ignored in source lists, unless it is the only token.
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-expected.txt
index b102913..a535d87 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-expected.txt
@@ -50,6 +50,11 @@
         padding-right: 10px; @[26:8-26:28]
         padding-right: 10px; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 Dumping inherited rules: 
     padding-top: 20px; @[0:0-0:18]
     padding-top: 20px; @[undefined-undefined]
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt
index 2a59321e..4ce6298 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt
@@ -31,6 +31,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 Dumping inherited rules: 
 
 Running test: testBasicPropertyChange
@@ -64,6 +69,11 @@
         padding-left: 101px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testChangePropertyInShortHand
 {
@@ -96,6 +106,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testChangeImportantProperty
 {
@@ -128,6 +143,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testChangeInlineProperty
 {
@@ -160,6 +180,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testChangeInlineImportantProperty
 {
@@ -192,6 +217,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testChangeMissingProperty
 {
@@ -226,6 +256,11 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
 Running test: testAppendWithSeparator
 Dumping inline style: 
@@ -274,4 +309,9 @@
         padding-left: 10px; @[undefined-undefined]
         margin-top: 15px !important; @[undefined-undefined]
     }
+@supports (display: grid) or (display: inline-grid)
+    *#inspected* {    regular
+        display: grid; @[32:8-32:22]
+        display: grid; @[undefined-undefined]
+    }
 
diff --git a/third_party/blink/web_tests/inspector-protocol/css/resources/set-active-property-value.css b/third_party/blink/web_tests/inspector-protocol/css/resources/set-active-property-value.css
index c281911..ec6c322 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/resources/set-active-property-value.css
+++ b/third_party/blink/web_tests/inspector-protocol/css/resources/set-active-property-value.css
@@ -27,3 +27,9 @@
         padding-right: 10px;
     }
 }
+
+@supports (display: grid) or (display: inline-grid) {
+    #inspected {
+        display: grid;
+    }
+}
diff --git a/third_party/blink/web_tests/inspector-protocol/resources/css-helper.js b/third_party/blink/web_tests/inspector-protocol/resources/css-helper.js
index 4040aea..9970fe5f 100644
--- a/third_party/blink/web_tests/inspector-protocol/resources/css-helper.js
+++ b/third_party/blink/web_tests/inspector-protocol/resources/css-helper.js
@@ -91,6 +91,13 @@
       baseIndent += 4;
     }
 
+    const supports = rule.supports || [];
+    const supportsLine = supports.map(s => s.text).join(' ');
+    if (supportsLine.length) {
+      this._indentLog(baseIndent, '@supports ' + supportsLine);
+      baseIndent += 4;
+    }
+
     var selectorLine = '';
     var selectors = rule.selectorList.selectors;
     for (var i = 0; i < selectors.length; ++i) {
diff --git a/third_party/blink/web_tests/virtual/layout_ng_table_frag/README.md b/third_party/blink/web_tests/virtual/layout_ng_table_frag/README.md
new file mode 100644
index 0000000..d856107
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/layout_ng_table_frag/README.md
@@ -0,0 +1 @@
+Testing LayoutNGTableFragmentation; see ../../VirtualTestSuites
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.https.window-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.https.window-expected.txt
new file mode 100644
index 0000000..8515ef7e
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS treat-as-public to local: failure.
+PASS treat-as-public to private: failure.
+PASS public to public: success.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.window-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.window-expected.txt
new file mode 100644
index 0000000..8515ef7e
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/nested-worker.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS treat-as-public to local: failure.
+PASS treat-as-public to private: failure.
+PASS public to public: success.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt
new file mode 100644
index 0000000..995bfcc5
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.https.window-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+PASS local to local: success.
+PASS private to local: failed preflight.
+PASS private to local: success.
+PASS private to private: success.
+PASS public to local: failed preflight.
+PASS public to local: success.
+PASS public to private: failed preflight.
+PASS public to private: success.
+PASS public to public: success.
+PASS treat-as-public to local: failed preflight.
+PASS treat-as-public to local: success.
+PASS treat-as-public to private: failed preflight.
+PASS treat-as-public to private: success.
+PASS treat-as-public to public: success.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt
new file mode 100644
index 0000000..c62a7d31
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/fetch/private-network-access/worker-fetch.window-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+PASS local to local: success.
+PASS private to local: failure.
+PASS private to private: success.
+PASS public to local: failure.
+PASS public to private: failure.
+PASS public to public: success.
+PASS treat-as-public to local: failure.
+PASS treat-as-public to private: failure.
+PASS treat-as-public to public: success.
+PASS private https to local: failure.
+PASS public https to private: failure.
+PASS public https to local: failure.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
index 7a802f02..e0cb627 100644
--- a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
+++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/dedicated-worker.https-expected.txt
@@ -7,5 +7,11 @@
 PASS COEP: none module worker in COEP: require-corp frame
 PASS COEP: require-corp module worker in COEP: none frame
 PASS COEP: require-corp module worker in COEP: require-corp frame
+PASS COEP: worker inherits COEP for blob URL.
+FAIL COEP: worker inherits COEP from blob URL creator, not owner. assert_equals: expected "FAILED" but got "LOADED"
+PASS COEP: worker inherits COEP for data URL.
+PASS COEP: worker inherits COEP from owner, not data URL creator.
+PASS COEP: worker inherits COEP for filesystem URL.
+FAIL COEP: worker inherits COEP from filesystem URL creator, not owner. assert_equals: expected "FAILED" but got "LOADED"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl
index 67d04f0..cf10e0d 100644
--- a/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl
+++ b/third_party/blink/web_tests/webgpu/internal_cts_test_splits.pyl
@@ -16,10 +16,10 @@
 [
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,validation,encoding,cmds,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*',
 
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc1-rgba-unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc1-rgba-unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm";*',
 
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="2d";readMethod="CopyToBuffer";format="rgba8unorm";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,resource_init,texture_zero:uninitialized_texture_is_zero:dimension="3d";readMethod="CopyToBuffer";format="rgba8unorm";*',
@@ -148,13 +148,19 @@
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:max_buffers_and_attribs:format="uint8x2";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,vertex_state,correctness:overlapping_attributes:format="uint8x2";*',
 
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
 
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*',
 
   'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="rgba8unorm";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="offscreen";dstColorFormat="rgba8unorm";*',
@@ -164,6 +170,11 @@
   'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl";dstColorFormat="rgba8unorm";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gl_context_canvas:canvasType="offscreen";contextName="webgl2";dstColorFormat="rgba8unorm";*',
 
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*',
+  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*',
+
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="FullCopyT2B";format="r8unorm";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="WriteTexture";checkMethod="PartialCopyT2B";format="r8unorm";*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:api,operation,command_buffer,image_copy:mip_levels:initMethod="CopyB2T";checkMethod="FullCopyT2B";format="r8unorm";*',
@@ -235,59 +246,4 @@
   'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="workgroup";workgroupSize=[7,7,3];batch__=0;*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="private";workgroupSize=[1,1,1];batch__=0;*',
   'wpt_internal/webgpu/cts.https.html?q=webgpu:shader,execution,zero_init:compute,zero_init:storageClass="function";workgroupSize=[1,1,1];batch__=0;*',
-
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="onscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rg32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="bgra8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgb10a2unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="rgba32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rg32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="bgra8unorm-srgb";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgb10a2unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba16float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="rgba32float";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=false;dstColorFormat="r8unorm";*',
-  'wpt_internal/webgpu/cts.https.html?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_gpu_context_canvas:canvasType="offscreen";srcAndDstInSameGPUDevice=true;dstColorFormat="r16float";*',
 ]
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
index d698476..13e0200 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
@@ -79,182 +79,182 @@
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:single:*'>
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:state_transitions:*'>
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyBufferToBuffer:copy_order:*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="r32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg11b10ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgb9e5ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rg32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:format="rgba32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="r32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba8sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg11b10ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgb9e5ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rg32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba16uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba16sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba16float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba32uint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba32sint";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:format="rgba32float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc1-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc1-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc2-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc2-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc3-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc3-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc4-r-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc4-r-snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc5-rg-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc5-rg-snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc6h-rgb-ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc6h-rgb-float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc7-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="bc7-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgb8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgb8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgb8a1unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgb8a1unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="etc2-rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="eac-r11unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="eac-r11snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="eac-rg11unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="eac-rg11snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-4x4-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-4x4-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-5x4-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-5x4-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-5x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-5x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-6x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-6x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-6x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-6x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x8-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-8x8-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x8-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x8-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x10-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-10x10-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-12x10-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-12x10-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-12x12-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:format="astc-12x12-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc1-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc1-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc2-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc2-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc3-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc3-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc4-r-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc4-r-snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc5-rg-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc5-rg-snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc6h-rgb-ufloat";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc6h-rgb-float";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc7-rgba-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="bc7-rgba-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgb8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgb8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgb8a1unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgb8a1unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="etc2-rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="eac-r11unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="eac-r11snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="eac-rg11unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="eac-rg11snorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-4x4-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-4x4-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-5x4-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-5x4-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-5x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-5x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-6x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-6x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-6x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-6x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x8-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-8x8-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x5-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x5-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x6-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x6-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x8-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x8-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x10-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-10x10-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-12x10-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-12x10-unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-12x12-unorm";*'>
-<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:format="astc-12x12-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg11b10ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgb9e5ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,non_array:srcFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba8sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg11b10ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgb9e5ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32uint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32sint";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,non_compressed,array:srcFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc1-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc2-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc2-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc3-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc3-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc4-r-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc4-r-snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc5-rg-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc5-rg-snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc6h-rgb-ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc6h-rgb-float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc7-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="bc7-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8a1unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgb8a1unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="etc2-rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-r11unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-r11snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-rg11unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="eac-rg11snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-4x4-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-4x4-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x4-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x4-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-5x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-6x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x8-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-8x8-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x8-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x8-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x10-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-10x10-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x10-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x10-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x12-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,non_array:srcFormat="astc-12x12-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc1-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc2-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc2-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc3-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc3-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc4-r-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc4-r-snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc5-rg-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc5-rg-snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc6h-rgb-ufloat";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc6h-rgb-float";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc7-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="bc7-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8a1unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgb8a1unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="etc2-rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-r11unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-r11snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-rg11unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="eac-rg11snorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-4x4-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-4x4-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x4-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x4-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-5x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-6x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x8-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-8x8-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x5-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x5-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x6-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x6-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x8-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x8-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x10-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-10x10-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x10-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x10-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x12-unorm";*'>
+<meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:color_textures,compressed,array:srcFormat="astc-12x12-unorm-srgb";*'>
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:zero_sized:*'>
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_depth_stencil:*'>
 <meta name=variant content='?q=webgpu:api,operation,command_buffer,copyTextureToTexture:copy_multisampled_color:*'>
@@ -2498,7 +2498,6 @@
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="WriteTexture";*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="CopyB2T";*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:origin_alignment:method="CopyT2B";*'>
-<meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:1d:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:size_alignment:*'>
 <meta name=variant content='?q=webgpu:api,validation,image_copy,texture_related:copy_rectangle:*'>
 <meta name=variant content='?q=webgpu:api,validation,initialization,requestDevice:features,nonexistent:*'>
@@ -2717,7 +2716,6 @@
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,log:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,log2:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,max:*'>
-<meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,min:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,mix_all_same_type_operands:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,vector_mix_with_scalar_blending_factor:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,float_built_functions:float_builtin_functions,scalar_case_modf:*'>
@@ -2750,6 +2748,7 @@
 <meta name=variant content='?q=webgpu:shader,execution,builtin,logical_built_in_functions:logical_builtin_functions,vector_select:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,min:integer_builtin_functions,unsigned_min:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,min:integer_builtin_functions,signed_min:*'>
+<meta name=variant content='?q=webgpu:shader,execution,builtin,min:float_builtin_functions,min:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,select:logical_builtin_functions,scalar_select:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,select:logical_builtin_functions,vector_select:*'>
 <meta name=variant content='?q=webgpu:shader,execution,builtin,value_testing_built_in_functions:value_testing_builtin_functions,isFinite:*'>
@@ -3235,84 +3234,162 @@
 <meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:onscreenCanvas,uploadToWebGL:*'>
 <meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:offscreenCanvas,snapshot:*'>
 <meta name=variant content='?q=webgpu:web_platform,canvas,readbackFromWebGPUCanvas:drawTo2DCanvas:*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";dstColorFormat="rgba32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";dstColorFormat="rgba32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";dstColorFormat="rgba32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";dstColorFormat="rgba32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";dstColorFormat="rgba32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="r8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="r16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="r32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rg8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rg16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rg32float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgba8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgba8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="bgra8unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="bgra8unorm-srgb";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgb10a2unorm";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgba16float";*'>
-<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="none";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_ImageData:alpha="premultiply";orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="none";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=true;dstColorFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:web_platform,copyToTexture,ImageBitmap:from_canvas:orientation="flipY";srcDoFlipYDuringCopy=false;dstColorFormat="rgba32float";*'>
 <meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r8unorm";*'>
 <meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r16float";*'>
 <meta name=variant content='?q=webgpu:web_platform,copyToTexture,canvas:copy_contents_from_2d_context_canvas:canvasType="onscreen";dstColorFormat="r32float";*'>
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index dc7cff0..02c473f 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -542,6 +542,15 @@
 
   global CLANG_REVISION, PACKAGE_VERSION, LLVM_BUILD_DIR
 
+  # TODO(crbug.com/1293292): Remove in the next Clang roll.
+  if args.llvm_force_head_revision:
+    global RELEASE_VERSION
+    RELEASE_VERSION = '15.0.0'
+    old_lib_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang', '14.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 e97b689..e624bd9 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 = '14.0.0'
+# TODO(crbug.com/1293292): Bump to 15.0.0 in the next Clang roll.
 
 CDS_URL = os.environ.get('CDS_CLANG_BUCKET_OVERRIDE',
     'https://commondatastorage.googleapis.com/chromium-browser-clang')
@@ -326,6 +327,11 @@
                       help='Verify that clang has the passed-in version.')
   args = parser.parse_args()
 
+  # TODO(crbug.com/1293292): Remove in the next Clang roll.
+  if args.llvm_force_head_revision:
+    global RELEASE_VERSION
+    RELEASE_VERSION = '15.0.0'
+
   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/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 229fe0c..57a868c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -85,7 +85,7 @@
       'Deterministic Android (dbg)': 'android_debug_bot',
 
       'android-arm64-proguard-rel': 'android_release_bot_minimal_symbols_arm64_webview_google',
-      'android-bfcache-rel': 'android_release_bot_minimal_symbols',
+      'android-no-bfcache-rel': 'android_release_bot_minimal_symbols',
       'android-binary-size-generator': 'android_binary_size',
       'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon_reclient',
       'android-cronet-arm-rel': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_reclient',
@@ -521,7 +521,7 @@
       'fuchsia-arm64-cast': 'release_bot_fuchsia_arm64_cast',
       'fuchsia-x64-cast': 'release_bot_fuchsia_cast',
       'fuchsia-x64-dbg': 'debug_bot_fuchsia_compile_only_reclient',
-      'linux-bfcache-rel': 'release_bot_blink',
+      'linux-no-bfcache-rel': 'release_bot_blink',
       'linux-bionic-rel': 'gpu_tests_release_bot',
       'linux-extended-tracing-rel': 'release_bot_extended_tracing',
       'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
@@ -788,7 +788,7 @@
 
     'tryserver.chromium.android': {
       'android-asan': 'android_clang_asan_release_trybot',
-      'android-bfcache-rel': 'android_release_trybot',
+      'android-no-bfcache-rel': 'android_release_trybot',
       'android-opus-arm-rel': 'android_release_trybot',
       'android-cronet-asan-arm-rel': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_clang_asan',
       # TODO(crbug/597596): Switch this back to debug_trybot when cronet's
@@ -1026,7 +1026,7 @@
       'linux-blink-heap-concurrent-marking-tsan-rel': 'release_trybot_tsan',
       'linux-blink-heap-verification-try': 'release_trybot_enable_blink_heap_verification',
       'linux-blink-v8-oilpan': 'release_trybot_enable_v8_oilpan',
-      'linux-bfcache-rel': 'release_bot_blink',
+      'linux-no-bfcache-rel': 'release_bot_blink',
       'linux-bionic-rel': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange',
       'linux-clang-tidy-dbg': 'debug_bot',
       'linux-clang-tidy-rel': 'release_trybot',
diff --git a/tools/mb/mb_config_expectations/chromium.android.json b/tools/mb/mb_config_expectations/chromium.android.json
index c094e41..260ab487 100644
--- a/tools/mb/mb_config_expectations/chromium.android.json
+++ b/tools/mb/mb_config_expectations/chromium.android.json
@@ -152,19 +152,6 @@
       "use_goma": true
     }
   },
-  "android-bfcache-rel": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "strip_debug_info": true,
-      "symbol_level": 1,
-      "target_os": "android",
-      "use_goma": true
-    }
-  },
   "android-binary-size-generator": {
     "gn_args": {
       "android_channel": "stable",
@@ -477,6 +464,19 @@
       "use_goma": true
     }
   },
+  "android-no-bfcache-rel": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "strip_debug_info": true,
+      "symbol_level": 1,
+      "target_os": "android",
+      "use_goma": true
+    }
+  },
   "android-pie-arm64-coverage-experimental-rel": {
     "gn_args": {
       "dcheck_always_on": false,
diff --git a/tools/mb/mb_config_expectations/chromium.linux.json b/tools/mb/mb_config_expectations/chromium.linux.json
index 55587bc..48d64a47 100644
--- a/tools/mb/mb_config_expectations/chromium.linux.json
+++ b/tools/mb/mb_config_expectations/chromium.linux.json
@@ -194,16 +194,6 @@
       "use_remoteexec": true
     }
   },
-  "linux-bfcache-rel": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "use_goma": true
-    }
-  },
   "linux-bionic-rel": {
     "gn_args": {
       "dcheck_always_on": false,
@@ -235,6 +225,16 @@
       "use_goma": false
     }
   },
+  "linux-no-bfcache-rel": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "use_goma": true
+    }
+  },
   "linux-trusty-rel": {
     "gn_args": {
       "dcheck_always_on": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
index a9cc0be..17b121d 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -70,20 +70,6 @@
       "use_goma": true
     }
   },
-  "android-bfcache-rel": {
-    "gn_args": {
-      "blink_enable_generated_code_formatting": false,
-      "dcheck_always_on": true,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "strip_debug_info": true,
-      "symbol_level": 0,
-      "target_os": "android",
-      "use_goma": true
-    }
-  },
   "android-binary-size": {
     "gn_args": {
       "android_channel": "stable",
@@ -636,6 +622,20 @@
       "use_goma": true
     }
   },
+  "android-no-bfcache-rel": {
+    "gn_args": {
+      "blink_enable_generated_code_formatting": false,
+      "dcheck_always_on": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "strip_debug_info": true,
+      "symbol_level": 0,
+      "target_os": "android",
+      "use_goma": true
+    }
+  },
   "android-opus-arm-rel": {
     "gn_args": {
       "blink_enable_generated_code_formatting": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
index 04377f8..90ac032 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -450,16 +450,6 @@
       "use_goma": true
     }
   },
-  "linux-bfcache-rel": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "use_goma": true
-    }
-  },
   "linux-bionic-rel": {
     "gn_args": {
       "blink_enable_generated_code_formatting": false,
@@ -683,6 +673,16 @@
       "use_goma": true
     }
   },
+  "linux-no-bfcache-rel": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "use_goma": true
+    }
+  },
   "linux-perfetto-rel": {
     "gn_args": {
       "blink_enable_generated_code_formatting": false,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 808c995..e108187 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -53325,6 +53325,7 @@
   <int value="-498740735" label="ArcUsbHost:disabled"/>
   <int value="-498463128" label="MacSystemShareMenu:enabled"/>
   <int value="-498412005" label="EnableDrDc:disabled"/>
+  <int value="-497571337" label="SkipUndecryptablePasswords:enabled"/>
   <int value="-496989565"
       label="DesktopPWAsFlashAppNameInsteadOfOrigin:disabled"/>
   <int value="-496119023" label="WebXR:enabled"/>
@@ -53490,6 +53491,7 @@
   <int value="-366949535" label="KeyboardShortcutViewerApp:enabled"/>
   <int value="-365920680" label="ImageCaptureAPI:disabled"/>
   <int value="-365806433" label="BuiltInModuleAll:disabled"/>
+  <int value="-365039598" label="WebBluetooth:disabled"/>
   <int value="-364604989"
       label="LinkManagedNoticeToChromeUIManagementURL:disabled"/>
   <int value="-364587218" label="ResourceLoadScheduler:enabled"/>
@@ -53528,6 +53530,7 @@
       label="WebAuthenticationCrosPlatformAuthenticator:enabled"/>
   <int value="-344343842" label="disable-experimental-app-list"/>
   <int value="-343769596" label="ServiceWorkerScriptStreaming:disabled"/>
+  <int value="-343314036" label="WebBluetooth:enabled"/>
   <int value="-342421456" label="EnableOverviewRoundedCorners:disabled"/>
   <int value="-340622848" label="disable-javascript-harmony-shipping"/>
   <int value="-340255045" label="allow-nacl-socket-api"/>
@@ -54349,6 +54352,7 @@
   <int value="272631627" label="BookmarkAppsMac:enabled"/>
   <int value="273489120" label="CrostiniDiskResizing:disabled"/>
   <int value="274103741" label="enable-ntp-popular-sites"/>
+  <int value="275616740" label="ForceInitialSyncWhenDecryptionFails:disabled"/>
   <int value="277483398" label="ClipboardHistory:disabled"/>
   <int value="277565405" label="ContextualSearchDefinitions:disabled"/>
   <int value="278756320" label="disable-app-list-app-info"/>
@@ -54882,6 +54886,7 @@
   <int value="638865852" label="UsePreferredIntervalForVideo:disabled"/>
   <int value="640174751" label="AndroidMultipleDisplay:enabled"/>
   <int value="642037198" label="SoleIntegration:disabled"/>
+  <int value="642601306" label="ForceInitialSyncWhenDecryptionFails:enabled"/>
   <int value="642678255" label="ExoGamepadVibration:disabled"/>
   <int value="643068614"
       label="CrossOriginOpenerPolicyAccessReporting:enabled"/>
@@ -56287,6 +56292,7 @@
   <int value="1660491118" label="AllowAmbientEQ:enabled"/>
   <int value="1660772828" label="NtpModulesDragAndDrop:enabled"/>
   <int value="1661354480" label="BlockInsecurePrivateNetworkRequests:disabled"/>
+  <int value="1661870048" label="SkipUndecryptablePasswords:disabled"/>
   <int value="1661925474" label="silent-debugger-extension-api"/>
   <int value="1662466302" label="NtpRealboxUseGoogleGIcon:enabled"/>
   <int value="1663574600" label="WebViewDisplayCutout:enabled"/>
@@ -80549,6 +80555,25 @@
   <int value="9" label="Privacy Guide Promo Entry"/>
 </enum>
 
+<enum name="SettingsPrivacyGuideSettingsStates">
+  <int value="0" label="MSBB Remains On"/>
+  <int value="1" label="MSBB Turned Off"/>
+  <int value="2" label="MSBB Turned On"/>
+  <int value="3" label="MSBB Remains Off"/>
+  <int value="4" label="Cookies Remains Block 3P Incognito"/>
+  <int value="5" label="Cookies Turned to Block 3P"/>
+  <int value="6" label="Cookies Turned to Block 3P Incognito"/>
+  <int value="7" label="Cookies Remains Block 3P"/>
+  <int value="8" label="History Sync Remains On"/>
+  <int value="9" label="History Sync Turned Off"/>
+  <int value="10" label="History Sync Turned On"/>
+  <int value="11" label="History Sync Remains Off"/>
+  <int value="12" label="Safe Browsing Remains Enhanced"/>
+  <int value="13" label="Safe Browsing Turned To Standard"/>
+  <int value="14" label="Safe Browsing Turned to Enhanced"/>
+  <int value="15" label="Safe Browsing Remains Standard"/>
+</enum>
+
 <enum name="SettingsPrivacySandboxEnabled">
   <int value="0" label="PS enabled, allow all cookies"/>
   <int value="1" label="PS enabled, block 3P cookies"/>
@@ -82921,6 +82946,10 @@
   <int value="44" label="UMA_AUTOFILL_VIRTUAL_CARD_FILLED"/>
   <int value="45" label="UMA_WINDOW_ERROR"/>
   <int value="46" label="UMA_MODULE_INSTALL_FAILURE"/>
+  <int value="47" label="UMA_PRICE_TRACKING_SUCCESS"/>
+  <int value="48" label="UMA_PRICE_TRACKING_FAILURE"/>
+  <int value="49" label="UMA_PRIVACY_SANDBOX_ADD_INTEREST"/>
+  <int value="50" label="UMA_PRIVACY_SANDBOX_REMOVE_INTEREST"/>
 </enum>
 
 <enum name="SnapshotItemId">
diff --git a/tools/metrics/histograms/metadata/account_manager/histograms.xml b/tools/metrics/histograms/metadata/account_manager/histograms.xml
index d42393d..e52a4942 100644
--- a/tools/metrics/histograms/metadata/account_manager/histograms.xml
+++ b/tools/metrics/histograms/metadata/account_manager/histograms.xml
@@ -127,7 +127,7 @@
 </histogram>
 
 <histogram name="AccountManager.TokenLoadStatus"
-    enum="AccountManagerTokenLoadStatus" expires_after="2022-02-06">
+    enum="AccountManagerTokenLoadStatus" expires_after="2023-02-06">
   <owner>sinhak@chromium.org</owner>
   <owner>anastasiian@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 673106d..d853666 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1201,6 +1201,54 @@
   </summary>
 </histogram>
 
+<histogram
+    name="NavigationSuggestion.GetDomainInfoDelayBeforeAllowingNavigation"
+    units="ms" expires_after="2022-07-03">
+  <owner>meacer@chromium.org</owner>
+  <owner>blundell@chromium.org</owner>
+  <owner>security-enamel@chromium.org</owner>
+  <summary>
+    Records the time duration that PerformChecks() spent in calls to
+    GetDomainInfo() before the navigation was ultimately allowed to proceed.
+    Recorded only for navigations that
+    LookalikeUrlNavigationThrottle::PerfomChecks() directly allows to proceed
+    (i.e., not those that result in showing interstitials and/or digital asset
+    manifest checks).
+  </summary>
+</histogram>
+
+<histogram
+    name="NavigationSuggestion.IsLookalikeUrlDelayBeforeAllowingNavigation"
+    units="ms" expires_after="2022-07-03">
+  <owner>meacer@chromium.org</owner>
+  <owner>blundell@chromium.org</owner>
+  <owner>security-enamel@chromium.org</owner>
+  <summary>
+    Records the time duration that PerformChecks() spent in calls to
+    IsLookalikeUrl() before the navigation was ultimately allowed to proceed.
+    Recorded only for navigations that
+    LookalikeUrlNavigationThrottle::PerfomChecks() directly allows to proceed
+    (i.e., not those that result in showing interstitials and/or digital asset
+    manifest checks).
+  </summary>
+</histogram>
+
+<histogram
+    name="NavigationSuggestion.PerformChecksDelayBeforeAllowingNavigation"
+    units="ms" expires_after="2022-07-03">
+  <owner>meacer@chromium.org</owner>
+  <owner>blundell@chromium.org</owner>
+  <owner>security-enamel@chromium.org</owner>
+  <summary>
+    Records the time duration the navigation was deferred while PerformChecks()
+    was executing before the navigation was ultimately allowed to proceed.
+    Recorded only for navigations that
+    LookalikeUrlNavigationThrottle::PerfomChecks() directly allows to proceed
+    (i.e., not those that result in showing interstitials and/or digital asset
+    manifest checks).
+  </summary>
+</histogram>
+
 <histogram name="NavigationSuggestion.UpdateEngagedSitesDeferTime" units="ms"
     expires_after="2022-07-03">
   <owner>meacer@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index ad4e39a..60e8957 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -212,6 +212,18 @@
   </summary>
 </histogram>
 
+<histogram name="Settings.PrivacyGuide.SettingsStates"
+    enum="SettingsPrivacyGuideSettingsStates" expires_after="M104">
+  <owner>harrisonsean@chromium.org</owner>
+  <owner>rainhard@chromium.org</owner>
+  <owner>chrome-friendly-settings@google.com</owner>
+  <summary>
+    Records whether or not the user kept the same settings or changed it, and
+    the corresponding value, on every |Next| or |Back| button click inside of
+    Privacy guide.
+  </summary>
+</histogram>
+
 <histogram name="Settings.PrivacySandbox.Enabled"
     enum="SettingsPrivacySandboxEnabled" expires_after="2022-06-26">
   <owner>harrisonsean@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 6248c66..25beb70 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "9ed307b2d52a0af8d2e30ff51e34cdcd1a224f26",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/c388978ab5ee678b31251d5615403bbae949528e/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/edbf45d8bffa3f43f41d5dbebc4b878e06dc21b3/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
index 1d4532255..7f999b82 100755
--- a/tools/valgrind/asan/asan_symbolize.py
+++ b/tools/valgrind/asan/asan_symbolize.py
@@ -212,29 +212,6 @@
     return binary_path
 
 
-class CheckUTF8:
-  # This wraps stream and show warnings if stream gets invalid data as utf-8.
-  def __init__(self, stream):
-    self._stream = stream
-
-  def __iter__(self):
-    return self
-
-  def __next__(self):
-
-    l = self._stream.buffer.readline()
-
-    if not l:
-      raise StopIteration
-
-    try:
-      return l.decode()
-    except UnicodeDecodeError:
-      print("WARNING: asan_symbolize.py failed to decode %s (base64 encoded)" %
-            base64.b64encode(l).decode())
-      return ""
-
-
 def main():
   parser = argparse.ArgumentParser(description='Symbolize sanitizer reports.')
   parser.add_argument('--test-summary-json-file',
@@ -276,10 +253,7 @@
       symbolize_snippets_in_json(args.test_summary_json_file, loop)
     else:
       # Process stdin.
-      if sys.version_info.major > 2:
-        asan_symbolize.logfile = CheckUTF8(sys.stdin)
-      else:
-        asan_symbolize.logfile = sys.stdin
+      asan_symbolize.logfile = sys.stdin
       loop.process_logfile()
 
 
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc
index 55f3fb4d..3cf962f 100644
--- a/ui/accessibility/accessibility_features.cc
+++ b/ui/accessibility/accessibility_features.cc
@@ -23,15 +23,6 @@
       ::features::kEnableAccessibilityAriaVirtualContent);
 }
 
-// Enable exposing "display: none" nodes to the browser process AXTree
-const base::Feature kEnableAccessibilityExposeDisplayNone{
-    "AccessibilityExposeDisplayNone", base::FEATURE_DISABLED_BY_DEFAULT};
-
-bool IsAccessibilityExposeDisplayNoneEnabled() {
-  return base::FeatureList::IsEnabled(
-      ::features::kEnableAccessibilityExposeDisplayNone);
-}
-
 // Enable exposing the <html> element to the browser process AXTree
 // (as an ignored node).
 const base::Feature kEnableAccessibilityExposeHTMLElement{
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h
index 57f7e5ff..6114d05 100644
--- a/ui/accessibility/accessibility_features.h
+++ b/ui/accessibility/accessibility_features.h
@@ -20,12 +20,6 @@
 // property.
 AX_BASE_EXPORT bool IsAccessibilityAriaVirtualContentEnabled();
 
-AX_BASE_EXPORT extern const base::Feature kEnableAccessibilityExposeDisplayNone;
-
-// Returns true if "display: none" nodes should be exposed to the
-// browser process AXTree.
-AX_BASE_EXPORT bool IsAccessibilityExposeDisplayNoneEnabled();
-
 AX_BASE_EXPORT extern const base::Feature kEnableAccessibilityExposeHTMLElement;
 
 // Returns true if the <html> element should be exposed to the
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn
index 0c478c9b..ef5a94c1 100644
--- a/ui/webui/resources/cr_components/BUILD.gn
+++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -30,10 +30,10 @@
       "chromeos/multidevice_setup/all_set_2x_light.svg",
       "chromeos/cellular_setup/sim_detect_error.svg",
       "chromeos/cellular_setup/sim_detect_error_dark.svg",
-      "chromeos/cellular_setup/error_1x.png",
-      "chromeos/cellular_setup/error_2x.png",
-      "chromeos/cellular_setup/final_page_success_1x.png",
-      "chromeos/cellular_setup/final_page_success_2x.png",
+      "chromeos/cellular_setup/error.svg",
+      "chromeos/cellular_setup/error_dark.svg",
+      "chromeos/cellular_setup/final_page_success.svg",
+      "chromeos/cellular_setup/final_page_success_dark.svg",
       "chromeos/cellular_setup/default_esim_profile.svg",
       "chromeos/cellular_setup/default_esim_profile_dark.svg",
       "chromeos/network/cellular_0_with_x.svg",
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/error.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/error.svg
new file mode 100644
index 0000000..dcf88610
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/error.svg
@@ -0,0 +1 @@
+<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M122.984 41.38c-25.952 0-46.99 21.015-46.99 46.939s21.038 46.94 46.99 46.94 46.991-21.016 46.991-46.94-21.039-46.94-46.991-46.94zm0 1.928c24.886 0 45.06 20.152 45.06 45.011s-20.174 45.011-45.06 45.011c-24.886 0-45.06-20.152-45.06-45.011s20.174-45.01 45.06-45.01z" fill="#D2E3FC"/><path d="M133.249 89.338h-11.877v11.574h-13.557a.39.39 0 0 1-.272-.668l25.044-24.408a.39.39 0 0 1 .662.28v13.222zm-1.288 3.1l-1.815-1.814-2.691 2.688-2.69-2.688-1.816 1.813 2.691 2.688-2.691 2.688 1.816 1.813 2.69-2.675 2.691 2.675 1.815-1.813-2.677-2.688 2.677-2.688z" fill="#D2E3FC"/><path fill-rule="evenodd" clip-rule="evenodd" d="M157.595 158.993c0-13.495-10.951-24.435-24.461-24.435-13.509 0-24.461 10.94-24.461 24.435" fill="#F1F3F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M48.74 134.835l1.893 2.7a2.532 2.532 0 0 1-.62 3.527l-.002.002-24.851 17.382a2.533 2.533 0 0 1-3.525-.622l-1.893-2.7a2.532 2.532 0 0 1 .62-3.527l.002-.002 24.851-17.382a2.532 2.532 0 0 1 3.525.622z" fill="#EE5FFA"/><path d="M50.548 159.017c4.33.999 8.65-1.697 9.648-6.022.999-4.326-1.702-8.643-6.032-9.642-4.33-1-8.649 1.696-9.647 6.022-.999 4.325 1.701 8.642 6.031 9.642z" fill="#F1F3F4"/><path d="M68.12 147.061c11.198 0 20.276-9.068 20.276-20.254 0-11.187-9.078-20.255-20.277-20.255-11.198 0-20.276 9.068-20.276 20.255 0 11.186 9.078 20.254 20.276 20.254z" fill="#FBBC04"/><path d="M69.88 130.279v-.746c0-.617.116-1.14.348-1.569.232-.429.64-.909 1.223-1.44.72-.669 1.296-1.334 1.725-1.994.43-.66.644-1.444.644-2.353 0-.909-.228-1.732-.683-2.469-.454-.738-1.09-1.321-1.905-1.749-.815-.429-1.746-.643-2.794-.643-1.407 0-2.566.394-3.476 1.183-.91.789-1.536 1.697-1.88 2.726l2.473 1.029c.223-.669.57-1.222 1.042-1.659.472-.437 1.095-.656 1.867-.656.807 0 1.442.219 1.906.656.463.437.695.99.695 1.659 0 .549-.133 1.02-.4 1.415-.266.394-.699.857-1.3 1.389-.858.771-1.454 1.448-1.79 2.031-.334.583-.501 1.295-.501 2.135v1.055h2.806zm-1.416 6.018a1.82 1.82 0 0 0 1.352-.565c.369-.378.553-.832.553-1.364 0-.531-.184-.986-.553-1.363a1.82 1.82 0 0 0-1.352-.566c-.532 0-.987.185-1.364.553a1.846 1.846 0 0 0-.567 1.376c0 .532.189.986.567 1.364.377.377.832.565 1.364.565z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M62.197 156.996c-.52.906.13 2.039 1.17 2.039H73.98c1.039 0 1.688-1.133 1.169-2.039l-5.308-9.255a1.346 1.346 0 0 0-2.338 0l-5.307 9.255z" fill="#EA4335"/><path d="M191.495 159.035a.965.965 0 0 1 .093 1.925l-.093.004H13.831a.965.965 0 0 1-.093-1.924l.093-.005h177.664z" fill="#D2E3FC"/><path d="M97.578 158.993c7.638 0 13.83-6.192 13.83-13.83s-6.192-13.83-13.83-13.83-13.83 6.192-13.83 13.83 6.192 13.83 13.83 13.83z" fill="#4285F4"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/error_1x.png b/ui/webui/resources/cr_components/chromeos/cellular_setup/error_1x.png
deleted file mode 100644
index ae6f33f..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/error_1x.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/error_2x.png b/ui/webui/resources/cr_components/chromeos/cellular_setup/error_2x.png
deleted file mode 100644
index dcfd0bd..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/error_2x.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/error_dark.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/error_dark.svg
new file mode 100644
index 0000000..0278deb
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/error_dark.svg
@@ -0,0 +1 @@
+<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M122.984 41.38c-25.952 0-46.99 21.015-46.99 46.939s21.038 46.94 46.99 46.94 46.991-21.016 46.991-46.94-21.039-46.94-46.991-46.94zm0 1.928c24.886 0 45.06 20.152 45.06 45.011s-20.174 45.011-45.06 45.011c-24.886 0-45.06-20.152-45.06-45.011s20.174-45.01 45.06-45.01z" fill="#8AB4F8" fill-opacity=".4"/><path d="M133.249 89.338h-11.877v11.574h-13.557a.39.39 0 0 1-.272-.668l25.044-24.408a.39.39 0 0 1 .662.28v13.222zm-1.288 3.1l-1.815-1.814-2.691 2.688-2.69-2.688-1.816 1.813 2.691 2.688-2.691 2.688 1.816 1.813 2.69-2.675 2.691 2.675 1.815-1.813-2.677-2.688 2.677-2.688z" fill="#8AB4F8" fill-opacity=".4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M157.595 158.993c0-13.495-10.951-24.435-24.461-24.435-13.509 0-24.461 10.94-24.461 24.435" fill="#5F6368"/><path fill-rule="evenodd" clip-rule="evenodd" d="M48.74 134.835l1.893 2.7a2.532 2.532 0 0 1-.62 3.527l-.002.002-24.851 17.382a2.533 2.533 0 0 1-3.525-.622l-1.893-2.7a2.532 2.532 0 0 1 .62-3.527l.002-.002 24.851-17.382a2.532 2.532 0 0 1 3.525.622z" fill="#F882FE"/><path d="M50.548 159.017c4.33.999 8.65-1.697 9.648-6.022.999-4.326-1.702-8.643-6.032-9.642-4.33-1-8.649 1.696-9.647 6.022-.999 4.325 1.701 8.642 6.031 9.642z" fill="#5F6368"/><path d="M68.12 147.061c11.198 0 20.276-9.068 20.276-20.254 0-11.187-9.078-20.255-20.277-20.255-11.198 0-20.276 9.068-20.276 20.255 0 11.186 9.078 20.254 20.276 20.254z" fill="#FCC934"/><path d="M69.88 130.279v-.746c0-.617.116-1.14.348-1.569.232-.429.64-.909 1.223-1.44.72-.669 1.296-1.334 1.725-1.994.43-.66.644-1.444.644-2.353 0-.909-.228-1.732-.683-2.469-.454-.738-1.09-1.321-1.905-1.749-.815-.429-1.746-.643-2.794-.643-1.407 0-2.566.394-3.476 1.183-.91.789-1.536 1.697-1.88 2.726l2.473 1.029c.223-.669.57-1.222 1.042-1.659.472-.437 1.095-.656 1.867-.656.807 0 1.442.219 1.906.656.463.437.695.99.695 1.659 0 .549-.133 1.02-.4 1.415-.266.394-.699.857-1.3 1.389-.858.771-1.454 1.448-1.79 2.031-.334.583-.501 1.295-.501 2.135v1.055h2.806zm-1.416 6.018a1.82 1.82 0 0 0 1.352-.565c.369-.378.553-.832.553-1.364 0-.531-.184-.986-.553-1.363a1.82 1.82 0 0 0-1.352-.566c-.532 0-.987.185-1.364.553a1.846 1.846 0 0 0-.567 1.376c0 .532.189.986.567 1.364.377.377.832.565 1.364.565z" fill="#323336"/><path fill-rule="evenodd" clip-rule="evenodd" d="M62.197 156.996c-.52.906.13 2.039 1.17 2.039H73.98c1.039 0 1.688-1.133 1.169-2.039l-5.308-9.255a1.346 1.346 0 0 0-2.338 0l-5.307 9.255z" fill="#EA4335"/><path d="M191.495 159.035a.965.965 0 0 1 .093 1.925l-.093.004H13.831a.965.965 0 0 1-.093-1.924l.093-.005h177.664z" fill="#8AB4F8" fill-opacity=".4"/><path d="M97.578 158.993c7.638 0 13.83-6.192 13.83-13.83s-6.192-13.83-13.83-13.83-13.83 6.192-13.83 13.83 6.192 13.83 13.83 13.83z" fill="#669DF6"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
index 97cbedd7..d58d9b4 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.html
@@ -8,9 +8,7 @@
   <template>
     <style>
       [slot='page-body'] {
-        background-image: -webkit-image-set(
-            url(chrome://resources/cr_components/chromeos/cellular_setup/final_page_success_1x.png) 1x,
-            url(chrome://resources/cr_components/chromeos/cellular_setup/final_page_success_2x.png) 2x);
+        background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/final_page_success.svg);
         background-position: center center;
         background-repeat: no-repeat;
         background-size: contain;
@@ -18,11 +16,19 @@
       }
 
       .error[slot='page-body'] {
-          background-image: -webkit-image-set(
-              url(chrome://resources/cr_components/chromeos/cellular_setup/error_1x.png) 1x,
-              url(chrome://resources/cr_components/chromeos/cellular_setup/error_2x.png) 2x);
+          background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/error.svg);
           background-size: contain;
       }
+
+      @media(prefers-color-scheme: dark) {
+        [slot='page-body'] {
+          background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg);
+        }
+
+        .error[slot='page-body'] {
+            background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/error_dark.svg);
+        }
+      }
     </style>
     <base-page title="[[getTitle_(showError)]]"
         message="[[getMessage_(showError)]]">
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg
new file mode 100644
index 0000000..076f2b6
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg
@@ -0,0 +1 @@
+<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#D2E3FC"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#D2E3FC"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#4285F4"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#4285F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#4285F4"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#34A853"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FBBC04"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778c-.49.859-1.716.859-2.207 0l-5.01-8.778z" fill="#2FE2EA"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1L99.765 43.748a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#fff"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_1x.png b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_1x.png
deleted file mode 100644
index 9c49b7a..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_1x.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_2x.png b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_2x.png
deleted file mode 100644
index f4869f8..0000000
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_2x.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg
new file mode 100644
index 0000000..d923316
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg
@@ -0,0 +1 @@
+<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#8AB4F8" fill-opacity=".4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#8AB4F8" fill-opacity=".4"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#669DF6"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#669DF6"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#669DF6"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#5BB974"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FCC934"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778c-.49.859-1.716.859-2.207 0l-5.01-8.778z" fill="#5DF1F2"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1L99.765 43.748a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#323336"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
index ba6ac6e..95978cc 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
@@ -24,15 +24,19 @@
       }
 
       #error-icon-container {
-        background-image: -webkit-image-set(
-            url(chrome://resources/cr_components/chromeos/cellular_setup/error_1x.png) 1x,
-            url(chrome://resources/cr_components/chromeos/cellular_setup/error_2x.png) 2x);
+        background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/error.svg);
         background-position: center center;
         background-repeat: no-repeat;
         background-size: contain;
         height: 100%;
         width: 100%;
       }
+
+      @media(prefers-color-scheme: dark) {
+        #error-icon-container {
+          background-image: url(chrome://resources/cr_components/chromeos/cellular_setup/error_dark.svg);
+        }
+      }
     </style>
     <base-page title="[[getPageTitle_(
                             showError, carrierName_, hasCarrierPortalLoaded_)]]"