diff --git a/DEPS b/DEPS
index c6f547c..5e9bc03 100644
--- a/DEPS
+++ b/DEPS
@@ -297,15 +297,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': '67b05344b27e685deec98d2b9e658063a1e74585',
+  'skia_revision': 'f905f5fd8a0634968ed2cf148366cb4f9d47d187',
   # 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': '00c85fe868b1aaa4f755105d06f82ec26b10d875',
+  'v8_revision': 'ea886d2b938b23acfae05995d45d06f3768007d1',
   # 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': 'be7084466521cb1b09e4d3bf39f5014e9e73d176',
+  'angle_revision': '88dd868f21502cfa4fab9b5ff4e6bfe5dd1c4bfd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -313,7 +313,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '40a40484c7651c17d1abc6d9440079815581dae2',
+  'pdfium_revision': 'eae074eeaaa0e0404e08681962cca9b97068e85c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -324,7 +324,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:9.20220722.3.1',
+  'fuchsia_version': 'version:9.20220726.0.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -376,7 +376,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': '355c426bc8d5f88eabb8e3ad5186a5346efa1b06',
+  'devtools_frontend_revision': 'b56cdf4658defeae6d8e3d81a5055771b51ae1be',
   # 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.
@@ -412,7 +412,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': '4d1d143977dd4272dc61eb7c3f6fc96f539f77f8',
+  'dawn_revision': '77f83cd4d2cd3e2090406590c75921f99c68171e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1584,7 +1584,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e19e4f253f28cfb21c5a2c2587c98b77b978bb98',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'edae25d0fafd41295533f28a811d27df4af01531',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1827,7 +1827,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2d7aa5c114baacc93f52fdc6f5ece99153decf13',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@537a3749bc9941692b6321f8e155350e457bf6a6',
     'condition': 'checkout_src_internal',
   },
 
@@ -1879,7 +1879,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'VeFoLVxRGPYtMFxhWL2RbuIhieWqznvb3pM4G56W_qIC',
+        'version': 'j8I3HoFJWPgM84Ps48ehxStZz7EVIsqDkI7mpzGZZmcC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/components/arc/mojom/net.mojom b/ash/components/arc/mojom/net.mojom
index d0fbdf9..8fb7267 100644
--- a/ash/components/arc/mojom/net.mojom
+++ b/ash/components/arc/mojom/net.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 19
+// Next MinVersion: 20
 
 // This file defines the mojo interface between the ARC networking stack and
 // Chrome OS. There are three different groups of interactions:
@@ -455,6 +455,10 @@
   // exclude_routes will take precedence and the destination will be excluded
   // from the host network.
   [MinVersion=15] array<string>? exclude_routes;
+
+  // IPv4 and IPv6 addresses of DNS proxy. When this field is not empty ARC
+  // overrides the network DNS addresses with these addresses.
+  [MinVersion=19] array<string>? dns_proxy_addresses;
 };
 
 // Describes a Wifi network configuration that ARC has requested the host to
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc
index 80e09ad..d3e0b07 100644
--- a/ash/components/arc/net/arc_net_host_impl.cc
+++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -45,6 +45,27 @@
 
 constexpr int kGetNetworksListLimit = 100;
 
+std::string PackedIPAddressToString(sa_family_t family,
+                                    const std::string& data) {
+  if (family != AF_INET && family != AF_INET6) {
+    NET_LOG(ERROR) << "Invalid IP family " << family;
+    return "";
+  }
+  if (family == AF_INET && data.length() != sizeof(in_addr)) {
+    NET_LOG(ERROR) << "Invalid packed IPv4 data size " << data.length()
+                   << ", expected " << sizeof(in_addr);
+    return "";
+  }
+  if (family == AF_INET6 && data.length() != sizeof(in6_addr)) {
+    NET_LOG(ERROR) << "Invalid packed IPv6 data size " << data.length()
+                   << ", expected " << sizeof(in6_addr);
+    return "";
+  }
+
+  char buf[INET6_ADDRSTRLEN] = {0};
+  return !inet_ntop(family, data.data(), buf, sizeof(buf)) ? "" : buf;
+}
+
 chromeos::NetworkStateHandler* GetStateHandler() {
   return chromeos::NetworkHandler::Get()->network_state_handler();
 }
@@ -440,6 +461,22 @@
           IPv4AddressToString(arc_it->second.host_ipv4_addr());
       network->arc_ipv4_prefix_length =
           arc_it->second.ipv4_subnet().prefix_len();
+      // Fill in DNS proxy addresses.
+      network->dns_proxy_addresses = std::vector<std::string>();
+      if (arc_it->second.dns_proxy_ipv4_addr().length() > 0) {
+        auto dns_proxy_ipv4_addr = PackedIPAddressToString(
+            AF_INET, arc_it->second.dns_proxy_ipv4_addr());
+        if (!dns_proxy_ipv4_addr.empty()) {
+          network->dns_proxy_addresses->push_back(dns_proxy_ipv4_addr);
+        }
+      }
+      if (arc_it->second.dns_proxy_ipv6_addr().length() > 0) {
+        auto dns_proxy_ipv6_addr = PackedIPAddressToString(
+            AF_INET6, arc_it->second.dns_proxy_ipv6_addr());
+        if (!dns_proxy_ipv6_addr.empty()) {
+          network->dns_proxy_addresses->push_back(dns_proxy_ipv6_addr);
+        }
+      }
     }
     networks.push_back(std::move(network));
   }
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn
index 01d5ba0..3169a8de 100644
--- a/base/allocator/partition_allocator/BUILD.gn
+++ b/base/allocator/partition_allocator/BUILD.gn
@@ -281,13 +281,11 @@
     "//build/config/compiler:compiler_buildflags",
   ]
 
-  # TODO(https://crbug.com/1151236): Remove this dependency on Abseil once PA
-  # no longer includes any headers directly from base/.
-  deps = [ "//third_party/abseil-cpp:absl" ]
   configs += [
     ":partition_alloc_implementation",
     ":memory_tagging",
   ]
+  deps = []
   public_configs = []
   if (is_android) {
     # tagging.cc requires __arm_mte_set_* functions.
diff --git a/base/check_is_test.h b/base/check_is_test.h
index 999767469..47a0e04f 100644
--- a/base/check_is_test.h
+++ b/base/check_is_test.h
@@ -34,7 +34,7 @@
 //
 // `CHECK_IS_TEST` is thread safe.
 
-#define CHECK_IS_TEST() base::internal::check_is_test_impl();
+#define CHECK_IS_TEST() base::internal::check_is_test_impl()
 
 namespace base::internal {
 BASE_EXPORT void check_is_test_impl();
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index 9a62f039..33e6dc0 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -788,7 +788,7 @@
     p.wrapped_ptr_ = nullptr;
   }
 
-  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) {
+  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) noexcept {
     // Duplicate before releasing, in case the pointer is assigned to itself.
     T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
     Impl::ReleaseWrappedPtr(wrapped_ptr_);
@@ -830,7 +830,7 @@
   ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
   ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
 
-  ALWAYS_INLINE ~raw_ptr() = default;
+  ALWAYS_INLINE ~raw_ptr() noexcept = default;
 
 #endif  // BUILDFLAG(USE_BACKUP_REF_PTR)
 
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 4833a61..a12c462 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-9.20220725.3.1
+9.20220726.0.1
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index f9d6c0d..eda9833e 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -546,10 +546,9 @@
   SetNeedsPushProperties();
 }
 
-SkColor4f Layer::SafeOpaqueBackgroundColor(
-    SkColor4f host_background_color) const {
+SkColor4f Layer::SafeOpaqueBackgroundColor() const {
   if (contents_opaque()) {
-    if (!IsAttached() || !IsUsingLayerLists()) {
+    if (!IsUsingLayerLists()) {
       // In layer tree mode, PropertyTreeBuilder should have calculated the safe
       // opaque background color and called SetSafeOpaqueBackgroundColor().
       DCHECK(layer_tree_inputs());
@@ -558,12 +557,8 @@
     }
     // In layer list mode, the PropertyTreeBuilder algorithm doesn't apply
     // because it depends on the layer tree hierarchy. Instead we use
-    // background_color() if it's not transparent, or layer_tree_host_'s
-    // background_color(), with the alpha channel forced to be opaque.
-    SkColor4f color = background_color() == SkColors::kTransparent
-                          ? host_background_color
-                          : background_color();
-    return color.makeOpaque();
+    // background_color() made opaque.
+    return background_color().makeOpaque();
   }
   if (background_color().isOpaque()) {
     // The layer is not opaque while the background color is, meaning that the
@@ -575,13 +570,6 @@
   return background_color();
 }
 
-SkColor4f Layer::SafeOpaqueBackgroundColor() const {
-  SkColor4f host_background_color =
-      IsAttached() ? layer_tree_host()->pending_commit_state()->background_color
-                   : layer_tree_inputs()->safe_opaque_background_color;
-  return SafeOpaqueBackgroundColor(host_background_color);
-}
-
 void Layer::SetMasksToBounds(bool masks_to_bounds) {
   DCHECK(IsPropertyChangeAllowed());
   auto& inputs = EnsureLayerTreeInputs();
@@ -1466,8 +1454,7 @@
   layer->SetElementId(inputs.element_id);
   layer->SetHasTransformNode(has_transform_node());
   layer->SetBackgroundColor(inputs.background_color);
-  layer->SetSafeOpaqueBackgroundColor(
-      SafeOpaqueBackgroundColor(commit_state.background_color));
+  layer->SetSafeOpaqueBackgroundColor(SafeOpaqueBackgroundColor());
   layer->SetBounds(inputs.bounds);
   layer->SetTransformTreeIndex(transform_tree_index(property_trees));
   layer->SetEffectTreeIndex(effect_tree_index(property_trees));
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 588cecf..78dcfb3 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -169,8 +169,9 @@
     return layer_tree_inputs() && !layer_tree_inputs()->copy_requests.empty();
   }
 
-  // Set and get the background color for the layer. This color is not used by
-  // basic Layers, but subclasses may make use of it.
+  // Set and get the background color for the layer. This color is used to
+  // calculate the safe opaque background color. Subclasses may also use the
+  // color for other purposes.
   virtual void SetBackgroundColor(SkColor4f background_color);
   SkColor4f background_color() const {
     return inputs_.Read(*this).background_color;
@@ -185,17 +186,14 @@
   // contents_opaque().
   // If the layer says contents_opaque() is true, in layer tree mode, this
   // returns the value set by SetSafeOpaqueBackgroundColor() which should be an
-  // opaque color, and in layer list mode, returns an opaque color calculated
-  // from background_color() and the argument host_background_color.
+  // opaque color, and in layer list mode, returns background_color() which
+  // should be opaque (otherwise SetBackgroundColor() should have set
+  // contents_opaque to false).
   // Otherwise, it returns something non-opaque. It prefers to return the
   // background_color(), but if the background_color() is opaque (and this layer
   // claims to not be), then SkColors::kTransparent is returned to avoid
   // intrusive checkerboard where the layer is not covered by the
   // background_color().
-  SkColor4f SafeOpaqueBackgroundColor(SkColor4f host_background_color) const;
-
-  // Same as the one-argument version, except that host_background_color is
-  // layer_tree_host()->pending_commit_state()->background_color.
   SkColor4f SafeOpaqueBackgroundColor() const;
 
   // For layer tree mode only.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 42c26460..1b048dcb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -21,9 +21,9 @@
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.chromium.base.Promise;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.BooleanSupplier;
-import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.BackPressHelper;
@@ -97,9 +97,8 @@
     private static FirstRunActivityObserver sObserver;
 
     private boolean mPostNativeAndPolicyPagesCreated;
-    // Use hasValue() to simplify access. Will be null before initialized.
-    private final OneshotSupplierImpl<Boolean> mNativeSideIsInitializedSupplier =
-            new OneshotSupplierImpl<>();
+    /** Use {@link Promise#isFulfilled()} to verify whether the native has been initialized. */
+    private final Promise<Void> mNativeInitializationPromise = new Promise<>();
 
     private FirstRunFlowSequencer mFirstRunFlowSequencer;
 
@@ -325,7 +324,7 @@
     }
 
     private void onNativeDependenciesFullyInitialized() {
-        mNativeSideIsInitializedSupplier.set(true);
+        mNativeInitializationPromise.fulfill(null);
 
         onInternalStateChanged();
     }
@@ -358,7 +357,7 @@
     }
 
     private boolean areNativeAndPoliciesInitialized() {
-        return mNativeSideIsInitializedSupplier.hasValue() && isFlowKnown()
+        return mNativeInitializationPromise.isFulfilled() && isFlowKnown()
                 && this.getPolicyLoadListener().get() != null;
     }
 
@@ -370,13 +369,13 @@
 
         FirstRunFragment page = (FirstRunFragment) fragment;
         // Delay notifying the child page until native and the TemplateUrlService are initialized.
-        // Tracked by mNativeSideIsInitializedSupplier is ready. Otherwise if the next page handles
+        // Tracked by mNativeSideIsInitialized is ready. Otherwise if the next page handles
         // the default search engine, it will be missing dependencies. See https://crbug.com/1275950
         // for when this didn't work.
-        if (mNativeSideIsInitializedSupplier.hasValue()) {
+        if (mNativeInitializationPromise.isFulfilled()) {
             page.onNativeInitialized();
         } else {
-            mNativeSideIsInitializedSupplier.onAvailable((ignored) -> page.onNativeInitialized());
+            mNativeInitializationPromise.then((ignored) -> { page.onNativeInitialized(); });
         }
     }
 
@@ -526,7 +525,7 @@
 
     @Override
     public void acceptTermsOfService(boolean allowCrashUpload) {
-        assert mNativeSideIsInitializedSupplier.hasValue();
+        assert mNativeInitializationPromise.isFulfilled();
 
         // If default is true then it corresponds to opt-out and false corresponds to opt-in.
         UmaUtils.recordMetricsReportingDefaultOptIn(!DEFAULT_METRICS_AND_CRASH_REPORTING);
@@ -615,14 +614,14 @@
                 this, LocalizationUtils.substituteLocalePlaceholder(getString(url)));
     }
 
-    @VisibleForTesting
-    boolean hasPages() {
-        return mPagerAdapter != null && mPagerAdapter.getItemCount() > 0;
+    @Override
+    public Promise<Void> getNativeInitializationPromise() {
+        return mNativeInitializationPromise;
     }
 
     @VisibleForTesting
-    public boolean isNativeSideIsInitializedForTest() {
-        return mNativeSideIsInitializedSupplier.hasValue();
+    boolean hasPages() {
+        return mPagerAdapter != null && mPagerAdapter.getItemCount() > 0;
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFragment.java
index 84f8e7e..e972f88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFragment.java
@@ -13,7 +13,11 @@
     /**
      * Notifies that the object returned by {@link #getPageDelegate()} and its dependencies have
      * been fully initialized, including native initialization.
+     *
+     * TODO(https://crbug.com/1346301): Remove this method.
+     * @deprecated Use {@link FirstRunPageDelegate#getNativeInitializationPromise()} instead.
      */
+    @Deprecated
     default void onNativeInitialized() {}
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
index d24a5e0..f04a337 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
@@ -6,6 +6,7 @@
 
 import android.os.Bundle;
 
+import org.chromium.base.Promise;
 import org.chromium.base.supplier.OneshotSupplier;
 
 /**
@@ -92,4 +93,10 @@
      * Returns the supplier that supplies child account status.
      */
     OneshotSupplier<Boolean> getChildAccountStatusSupplier();
+
+    /**
+     * Returns the promise that provides information about native initialization. Callers can use
+     * {@link Promise#isFulfilled()} to check whether the native has already been initialized.
+     */
+    Promise<Void> getNativeInitializationPromise();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
index 224ce76..5fd50fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
@@ -74,7 +74,6 @@
     private @Nullable SigninFirstRunCoordinator mSigninFirstRunCoordinator;
     private @LoadPoint int mSlowestLoadPoint;
     private boolean mExitFirstRunCalled;
-    private boolean mNativeInitialized;
     private boolean mNativePolicyAndChildStatusLoaded;
     private boolean mAllowCrashUpload;
 
@@ -83,6 +82,9 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
+        mModalDialogManager = ((ModalDialogManagerHolder) getActivity()).getModalDialogManager();
+
+        getPageDelegate().getNativeInitializationPromise().then(result -> { onNativeLoaded(); });
         getPageDelegate().getPolicyLoadListener().onAvailable(hasPolicies -> onPolicyLoad());
         getPageDelegate().getChildAccountStatusSupplier().onAvailable(
                 ignored -> onChildAccountStatusAvailable());
@@ -93,7 +95,6 @@
                 if (skipTos) exitFirstRun();
             });
         }
-        mModalDialogManager = ((ModalDialogManagerHolder) getActivity()).getModalDialogManager();
     }
 
     @Override
@@ -155,20 +156,6 @@
 
     /** Implements {@link FirstRunFragment}. */
     @Override
-    public void onNativeInitialized() {
-        if (mNativeInitialized) return;
-        // This may happen when the native initialized supplier in FirstRunActivity calls back after
-        // the fragment has been detached from the activity. See https://crbug.com/1294998.
-        if (getPageDelegate() == null) return;
-
-        mNativeInitialized = true;
-        mSlowestLoadPoint = LoadPoint.NATIVE_INITIALIZATION;
-        getPageDelegate().recordNativeInitializedHistogram();
-        notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded();
-    }
-
-    /** Implements {@link FirstRunFragment}. */
-    @Override
     public void reset() {
         if (mSigninFirstRunCoordinator != null) {
             mSigninFirstRunCoordinator.reset();
@@ -255,6 +242,16 @@
         }
     }
 
+    private void onNativeLoaded() {
+        // This may happen when the native initialized supplier in FirstRunActivity calls back after
+        // the fragment has been detached from the activity. See https://crbug.com/1294998.
+        if (getPageDelegate() == null) return;
+
+        mSlowestLoadPoint = LoadPoint.NATIVE_INITIALIZATION;
+        getPageDelegate().recordNativeInitializedHistogram();
+        notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded();
+    }
+
     private void onChildAccountStatusAvailable() {
         mSlowestLoadPoint = LoadPoint.CHILD_STATUS_LOAD;
         notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded();
@@ -274,20 +271,18 @@
         // the fragment has been detached from the activity. See https://crbug.com/1294998.
         if (getPageDelegate() == null) return;
 
-        if (mSigninFirstRunCoordinator != null && mNativeInitialized
+        if (mSigninFirstRunCoordinator != null
+                && getPageDelegate().getNativeInitializationPromise().isFulfilled()
                 && getPageDelegate().getChildAccountStatusSupplier().get() != null
-                && getPageDelegate().getPolicyLoadListener().get() != null) {
-            // Only notify once.
-            if (!mNativePolicyAndChildStatusLoaded) {
-                mNativePolicyAndChildStatusLoaded = true;
-                mAllowCrashUpload =
-                        !mSigninFirstRunCoordinator.isMetricsReportingDisabledByPolicy();
-                mSigninFirstRunCoordinator.onNativePolicyAndChildStatusLoaded(
-                        getPageDelegate().getPolicyLoadListener().get());
-                getPageDelegate().recordNativePolicyAndChildStatusLoadedHistogram();
-                RecordHistogram.recordEnumeratedHistogram(
-                        "MobileFre.SlowestLoadPoint", mSlowestLoadPoint, LoadPoint.MAX);
-            }
+                && getPageDelegate().getPolicyLoadListener().get() != null
+                && !mNativePolicyAndChildStatusLoaded) {
+            mNativePolicyAndChildStatusLoaded = true;
+            mAllowCrashUpload = !mSigninFirstRunCoordinator.isMetricsReportingDisabledByPolicy();
+            mSigninFirstRunCoordinator.onNativePolicyAndChildStatusLoaded(
+                    getPageDelegate().getPolicyLoadListener().get());
+            getPageDelegate().recordNativePolicyAndChildStatusLoadedHistogram();
+            RecordHistogram.recordEnumeratedHistogram(
+                    "MobileFre.SlowestLoadPoint", mSlowestLoadPoint, LoadPoint.MAX);
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java
index f644ffe..fa61367 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java
@@ -344,7 +344,8 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         mFirstRunActivity = ApplicationTestUtils.waitForActivityWithClass(
                 FirstRunActivity.class, Stage.RESUMED, () -> context.startActivity(intent));
-        CriteriaHelper.pollUiThread(mFirstRunActivity::isNativeSideIsInitializedForTest);
+        CriteriaHelper.pollUiThread(
+                () -> mFirstRunActivity.getNativeInitializationPromise().isFulfilled());
     }
 
     private static class LinkClick implements ViewAction {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
index c811951..0a55867 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -669,7 +669,8 @@
         CriteriaHelper.pollUiThread(
                 () -> freActivity.getSupportFragmentManager().getFragments().size() > 0);
         // Make sure native is initialized so that the subsequent transition is not blocked.
-        CriteriaHelper.pollUiThread((() -> freActivity.isNativeSideIsInitializedForTest()),
+        CriteriaHelper.pollUiThread(
+                (() -> freActivity.getNativeInitializationPromise().isFulfilled()),
                 "native never initialized.");
 
         waitForActivity(CustomTabActivity.class);
@@ -923,7 +924,8 @@
 
         launchViewIntent(TEST_URL);
         FirstRunActivity firstRunActivity = waitForActivity(FirstRunActivity.class);
-        CriteriaHelper.pollUiThread((() -> firstRunActivity.isNativeSideIsInitializedForTest()),
+        CriteriaHelper.pollUiThread(
+                (() -> firstRunActivity.getNativeInitializationPromise().isFulfilled()),
                 "native never initialized.");
 
         unblockOnFlowIsKnown();
@@ -987,7 +989,8 @@
 
         launchCustomTabs(TEST_URL);
         FirstRunActivity firstRunActivity = waitForActivity(FirstRunActivity.class);
-        CriteriaHelper.pollUiThread((() -> firstRunActivity.isNativeSideIsInitializedForTest()),
+        CriteriaHelper.pollUiThread(
+                (() -> firstRunActivity.getNativeInitializationPromise().isFulfilled()),
                 "native never initialized.");
 
         unblockOnFlowIsKnown();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
index f61a3f3..bee3194 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
@@ -20,6 +20,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.Promise;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.params.ParameterAnnotations;
 import org.chromium.base.test.params.ParameterProvider;
@@ -148,7 +149,11 @@
         mFragment = new CustomSigninFirstRunFragment();
         mFragment.setPageDelegate(mFirstRunPageDelegateMock);
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mFragment.onNativeInitialized();
+            Promise<Void> nativeSideIsInitialized = new Promise<>();
+            nativeSideIsInitialized.fulfill(null);
+            when(mFirstRunPageDelegateMock.getNativeInitializationPromise())
+                    .thenReturn(nativeSideIsInitialized);
+
             OneshotSupplierImpl<Boolean> childAccountStatusListener = new OneshotSupplierImpl<>();
             childAccountStatusListener.set(false);
             when(mFirstRunPageDelegateMock.getChildAccountStatusSupplier())
@@ -302,7 +307,6 @@
     public void testFragmentWhenCannotUseGooglePlayService(
             boolean nightModeEnabled, int orientation) throws IOException {
         when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(false);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
 
         launchActivityWithFragment(orientation);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
index a39ce12..4f4a6df 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
@@ -61,6 +61,7 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.Callback;
+import org.chromium.base.Promise;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.params.ParameterAnnotations;
@@ -170,6 +171,7 @@
     @Captor
     private ArgumentCaptor<Callback<Boolean>> mCallbackCaptor;
 
+    private Promise<Void> mNativeInitializationPromise;
     private FakeEnterpriseInfo mFakeEnterpriseInfo = new FakeEnterpriseInfo();
     private CustomSigninFirstRunFragment mFragment;
 
@@ -201,6 +203,15 @@
         SigninCheckerProvider.setForTests(mSigninCheckerMock);
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.DEFAULT);
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mNativeInitializationPromise = new Promise<>();
+            mNativeInitializationPromise.fulfill(null);
+            // Use thenAnswer in case mNativeSideIsInitialized is changed in some tests.
+            when(mFirstRunPageDelegateMock.getNativeInitializationPromise())
+                    .thenAnswer(ignored -> mNativeInitializationPromise);
+        });
+
         when(mPolicyLoadListenerMock.get()).thenReturn(false);
         when(mFirstRunPageDelegateMock.getPolicyLoadListener()).thenReturn(mPolicyLoadListenerMock);
         when(mChildAccountStatusListenerMock.get()).thenReturn(false);
@@ -226,7 +237,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenAddingAccountDynamically() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         Assert.assertFalse(
                 mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown());
@@ -241,7 +251,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenAddingChildAccountDynamically() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed()));
         onView(withText(R.string.signin_fre_dismiss_button)).check(matches(isDisplayed()));
@@ -257,7 +266,6 @@
     public void testFragmentWhenRemovingChildAccountDynamically() {
         mSigninTestRule.addAccount(
                 CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         mSigninTestRule.removeAccount(CHILD_ACCOUNT_EMAIL);
@@ -276,7 +284,6 @@
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null);
         mSigninTestRule.addAccount(
                 TEST_EMAIL2, /*fullName=*/null, /*givenName=*/null, /*avatar=*/null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         mSigninTestRule.removeAccount(TEST_EMAIL1);
@@ -288,7 +295,6 @@
     @MediumTest
     public void testRemovingAllAccountsDismissesAccountPickerDialog() {
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         onView(withText(TEST_EMAIL1)).perform(click());
         onView(withText(R.string.signin_account_picker_dialog_title))
@@ -305,7 +311,6 @@
     @Test
     @MediumTest
     public void testFragmentWithDefaultAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
 
         launchActivityWithFragment();
@@ -318,7 +323,6 @@
     @MediumTest
     public void testFragmentWhenCannotUseGooglePlayService() {
         when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(false);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
 
         launchActivityWithFragment();
 
@@ -342,7 +346,6 @@
         when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(true);
         when(mPolicyLoadListenerMock.get()).thenReturn(true);
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
 
         launchActivityWithFragment();
 
@@ -371,7 +374,6 @@
         })
                 .when(mSigninManagerMock)
                 .signin(eq(AccountUtils.createAccountFromName(TEST_EMAIL1)), any());
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
 
@@ -397,7 +399,6 @@
         });
         when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(true);
         when(mPolicyLoadListenerMock.get()).thenReturn(true);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         checkFragmentWhenSigninIsDisabledByPolicy();
 
@@ -410,7 +411,6 @@
     @MediumTest
     public void testContinueButtonWhenCannotUseGooglePlayService() {
         when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(false);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         CriteriaHelper.pollUiThread(() -> {
             return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown();
@@ -426,7 +426,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenChoosingAnotherAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         mSigninTestRule.addAccount(
                 TEST_EMAIL2, /* fullName= */ null, /* givenName= */ null, /* avatar= */ null);
@@ -443,7 +442,6 @@
     @MediumTest
     public void testFragmentWithDefaultAccountWhenPolicyAvailableOnDevice() {
         when(mPolicyLoadListenerMock.get()).thenReturn(true);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
 
         launchActivityWithFragment();
@@ -455,7 +453,6 @@
     @Test
     @MediumTest
     public void testFragmentWithChildAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(
                 CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null);
 
@@ -467,7 +464,6 @@
     @Test
     @MediumTest
     public void testSigninWithDefaultAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         launchActivityWithFragment();
         final String continueAsText = mChromeActivityTestRule.getActivity().getString(
@@ -494,7 +490,6 @@
     @Test
     @MediumTest
     public void testSigninWithNonDefaultAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, /*avatar=*/null);
         mSigninTestRule.addAccount(
                 TEST_EMAIL2, /*fullName=*/null, /*givenName=*/null, /*avatar=*/null);
@@ -527,7 +522,6 @@
         final CoreAccountInfo primaryAccount = mSigninTestRule.addTestAccountThenSignin();
         Assert.assertNotEquals("The primary account should be a different account!",
                 targetPrimaryAccount.getEmail(), primaryAccount.getEmail());
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         final String continueAsText = mChromeActivityTestRule.getActivity().getString(
@@ -562,7 +556,6 @@
                          Profile.getLastUsedRegularProfile()))
                     .thenReturn(mIdentityManagerMock);
         });
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         final String continueAsText = mChromeActivityTestRule.getActivity().getString(
@@ -581,7 +574,6 @@
         final CoreAccountInfo primaryAccount = mSigninTestRule.addTestAccountThenSignin();
         Assert.assertNotEquals("The primary account should be a different account!", TEST_EMAIL1,
                 primaryAccount.getEmail());
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         onView(withText(R.string.signin_fre_dismiss_button)).perform(click());
@@ -601,7 +593,6 @@
     @MediumTest
     public void testDismissButtonWithDefaultAccount() {
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         onView(withText(R.string.signin_fre_dismiss_button)).perform(click());
@@ -622,7 +613,6 @@
                     .thenReturn(mSigninManagerMock);
         });
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(
                 CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null);
         launchActivityWithFragment();
@@ -654,7 +644,6 @@
                          Profile.getLastUsedRegularProfile()))
                     .thenReturn(mIdentityManagerMock);
         });
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         final String continueAsText = mChromeActivityTestRule.getActivity().getString(
@@ -680,7 +669,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenClickingOnTosLink() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         onView(withId(R.id.signin_fre_footer)).perform(clickOnTosLink());
@@ -692,7 +680,6 @@
     @MediumTest
     @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
     public void testFragmentWhenClickingOnTosLinkInDarkMode(boolean nightModeEnabled) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         onView(withId(R.id.signin_fre_footer)).perform(clickOnTosLink());
@@ -705,7 +692,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenClickingOnUmaDialogLink() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
 
         clickOnUmaDialogLinkAndWait();
@@ -732,7 +718,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenDismissingUmaDialog() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         clickOnUmaDialogLinkAndWait();
 
@@ -744,7 +729,6 @@
     @Test
     @MediumTest
     public void testDismissButtonWhenAllowCrashUploadTurnedOff() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         clickOnUmaDialogLinkAndWait();
         onView(withId(R.id.fre_uma_dialog_switch)).perform(click());
@@ -759,7 +743,6 @@
     @Test
     @MediumTest
     public void testUmaDialogSwitchIsOffWhenAllowCrashUploadWasTurnedOffBefore() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         clickOnUmaDialogLinkAndWait();
         onView(withId(R.id.fre_uma_dialog_switch)).check(matches(isChecked())).perform(click());
@@ -780,7 +763,6 @@
     @Test
     @MediumTest
     public void testContinueButtonWhenAllowCrashUploadTurnedOff() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         launchActivityWithFragment();
         clickOnUmaDialogLinkAndWait();
@@ -798,7 +780,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenAddingAnotherAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         launchActivityWithFragment();
         onView(withText(TEST_EMAIL1)).perform(click());
@@ -820,7 +801,6 @@
     @Test
     @MediumTest
     public void testFragmentWhenAddingDefaultAccount() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         onView(withText(R.string.signin_add_account_to_device)).perform(click());
 
@@ -840,12 +820,12 @@
     @Test
     @MediumTest
     public void testFragmentWhenPolicyIsLoadedAfterNativeAndChildStatus() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         when(mPolicyLoadListenerMock.get()).thenReturn(null);
         launchActivityWithFragment();
         checkFragmentWhenLoadingNativeAndPolicy();
 
+        // TODO(https://crbug.com/1346258): Use OneshotSupplierImpl instead.
         when(mPolicyLoadListenerMock.get()).thenReturn(false);
         verify(mPolicyLoadListenerMock, atLeastOnce()).onAvailable(mCallbackCaptor.capture());
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -854,41 +834,43 @@
             }
         });
 
+        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
         Assert.assertEquals("Policy loading should be the slowest", 1,
                 mHistogramTestRule.getHistogramValueCount(
                         "MobileFre.SlowestLoadPoint", LoadPoint.POLICY_LOAD));
         Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1,
                 mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint"));
-        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
     }
 
     @Test
     @MediumTest
     public void testFragmentWhenNativeIsLoadedAfterPolicyAndChildStatus() {
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         checkFragmentWhenLoadingNativeAndPolicy();
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
+        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
         Assert.assertEquals("Native initialization should be the slowest", 1,
                 mHistogramTestRule.getHistogramValueCount(
                         "MobileFre.SlowestLoadPoint", LoadPoint.NATIVE_INITIALIZATION));
         Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1,
                 mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint"));
         verify(mFirstRunPageDelegateMock).recordNativeInitializedHistogram();
-        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
     }
 
     @Test
     @MediumTest
     public void testFragmentWhenChildStatusIsLoadedAfterNativeAndPolicy() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         mSigninTestRule.addAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1, null);
         when(mChildAccountStatusListenerMock.get()).thenReturn(null);
         launchActivityWithFragment();
         checkFragmentWhenLoadingNativeAndPolicy();
 
+        // TODO(https://crbug.com/1346258): Use OneshotSupplierImpl instead.
         when(mChildAccountStatusListenerMock.get()).thenReturn(false);
         verify(mChildAccountStatusListenerMock, atLeastOnce())
                 .onAvailable(mCallbackCaptor.capture());
@@ -898,18 +880,17 @@
             }
         });
 
+        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
         Assert.assertEquals("Child status loading should be the slowest", 1,
                 mHistogramTestRule.getHistogramValueCount(
                         "MobileFre.SlowestLoadPoint", LoadPoint.CHILD_STATUS_LOAD));
         Assert.assertEquals("SlowestLoadpoint histogram should be counted only once", 1,
                 mHistogramTestRule.getHistogramTotalCount("MobileFre.SlowestLoadPoint"));
-        checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1);
     }
 
     @Test
     @MediumTest
     public void testNativePolicyAndChildStatusLoadMetricRecordedOnlyOnce() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         launchActivityWithFragment();
         verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram();
         verify(mFirstRunPageDelegateMock).recordNativeInitializedHistogram();
@@ -936,7 +917,6 @@
     @Test
     @MediumTest
     public void testFragmentWithTosDialogBehaviorPolicy() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
         CallbackHelper callbackHelper = new CallbackHelper();
         doAnswer(invocation -> {
             callbackHelper.notifyCalled();
@@ -965,13 +945,15 @@
     public void testFragment_WelcomeToChrome() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.WELCOME_TO_CHROME);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.fre_native_and_policy_load_progress_spinner))
                 .check(matches(isDisplayed()));
         onView(withText(R.string.fre_welcome)).check(matches(isDisplayed()));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.fre_welcome)).check(matches(isDisplayed()));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
@@ -982,13 +964,15 @@
     public void testFragment_WelcomeToChrome_MostOutOfChrome() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.WELCOME_TO_CHROME_MOST_OUT_OF_CHROME);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.fre_native_and_policy_load_progress_spinner))
                 .check(matches(isDisplayed()));
         onView(withId(R.id.title)).check(matches(not(isDisplayed())));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.fre_welcome)).check(matches(isDisplayed()));
         onView(withText(R.string.signin_fre_subtitle_variation_1)).check(matches(isDisplayed()));
@@ -999,11 +983,13 @@
     public void testFragment_WelcomeToChrome_StrongestSecurity() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.WELCOME_TO_CHROME_STRONGEST_SECURITY);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.title)).check(matches(not(isDisplayed())));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.fre_welcome)).check(matches(isDisplayed()));
         onView(withText(R.string.signin_fre_subtitle_variation_2)).check(matches(isDisplayed()));
@@ -1014,13 +1000,15 @@
     public void testFragment_WelcomeToChrome_EasierAcrossDevices() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.WELCOME_TO_CHROME_EASIER_ACROSS_DEVICES);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.fre_native_and_policy_load_progress_spinner))
                 .check(matches(isDisplayed()));
         onView(withId(R.id.title)).check(matches(not(isDisplayed())));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.fre_welcome)).check(matches(isDisplayed()));
         onView(withText(R.string.signin_fre_subtitle_variation_3)).check(matches(isDisplayed()));
@@ -1031,13 +1019,15 @@
     public void testFragment_MostOutOfChrome() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.MOST_OUT_OF_CHROME);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.fre_native_and_policy_load_progress_spinner))
                 .check(matches(isDisplayed()));
         onView(withId(R.id.title)).check(matches(not(isDisplayed())));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.signin_fre_title_variation_1)).check(matches(isDisplayed()));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
@@ -1048,13 +1038,15 @@
     public void testFragment_MakeChromeYourOwn() {
         FREMobileIdentityConsistencyFieldTrial.setFirstRunVariationsTrialGroupForTesting(
                 VariationsGroup.MAKE_CHROME_YOUR_OWN);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { mNativeInitializationPromise = new Promise<>(); });
         launchActivityWithFragment();
         onView(withId(R.id.fre_native_and_policy_load_progress_spinner))
                 .check(matches(isDisplayed()));
         onView(withId(R.id.title)).check(matches(not(isDisplayed())));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> mNativeInitializationPromise.fulfill(null));
 
         onView(withText(R.string.signin_fre_title_variation_2)).check(matches(isDisplayed()));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index a6935b1..20719c77 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-105.0.5195.5_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-105.0.5195.6_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_factory.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_factory.cc
index c3f210d7..e940ce5 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_factory.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_factory.cc
@@ -41,6 +41,9 @@
 // app deduplication.
 bool AppDeduplicationServiceFactory::
     IsAppDeduplicationServiceAvailableForProfile(Profile* profile) {
+  if (!base::FeatureList::IsEnabled(features::kAppDeduplicationService)) {
+    return false;
+  }
   return AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile);
 }
 
diff --git a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
index 72df0196..17dba0b 100644
--- a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
+++ b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.cc
@@ -6,11 +6,52 @@
 
 #include <memory>
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "chrome/browser/apps/app_provisioning_service/proto/app_data.pb.h"
+#include "chrome/common/chrome_features.h"
 
 namespace apps {
 
+namespace {
+// TODO(b/238394602): Use fake data for now. Update to generate from real data
+// when real data is ready.
+std::unique_ptr<proto::DuplicatedAppsMap> PopulateDuplicatedAppsMap() {
+  std::unique_ptr<proto::DuplicatedAppsMap> duplicated_apps_map =
+      std::make_unique<proto::DuplicatedAppsMap>();
+  auto* map = duplicated_apps_map->mutable_duplicated_apps_map();
+  proto::DuplicateGroup duplicate_group;
+  auto* arc_app = duplicate_group.add_apps();
+  arc_app->set_app_id_for_platform("test_arc_app_id");
+  arc_app->set_source_name("arc");
+
+  auto* web_app = duplicate_group.add_apps();
+  web_app->set_app_id_for_platform("test_web_app_id");
+  web_app->set_source_name("web");
+
+  (*map)["test_key"] = duplicate_group;
+  return duplicated_apps_map;
+}
+
+std::unique_ptr<proto::AppWithLocaleList> PopulateAppWithLocaleList(
+    const std::string& binary_pb) {
+  // Parse the proto and do some validation on it.
+  if (binary_pb.empty()) {
+    LOG(ERROR) << "Binary is empty";
+    return nullptr;
+  }
+
+  std::unique_ptr<proto::AppWithLocaleList> app_with_locale_list =
+      std::make_unique<proto::AppWithLocaleList>();
+  if (!app_with_locale_list->ParseFromString(binary_pb)) {
+    LOG(ERROR) << "Failed to parse protobuf";
+    return nullptr;
+  }
+
+  return app_with_locale_list;
+}
+}  // namespace
+
 // static
 AppProvisioningDataManager* AppProvisioningDataManager::Get() {
   static base::NoDestructor<AppProvisioningDataManager> instance;
@@ -24,21 +65,11 @@
 void AppProvisioningDataManager::PopulateFromDynamicUpdate(
     const std::string& binary_pb,
     const base::FilePath& install_dir) {
-  // Parse the proto and do some validation on it.
-  if (binary_pb.empty()) {
-    LOG(ERROR) << "Binary is empty";
-    return;
-  }
-
-  std::unique_ptr<proto::AppWithLocaleList> app_with_locale_list =
-      std::make_unique<proto::AppWithLocaleList>();
-  if (!app_with_locale_list->ParseFromString(binary_pb)) {
-    LOG(ERROR) << "Failed to parse protobuf";
-    return;
-  }
-
   // TODO(melzhang) : Add check that version of |app_with_locale_list| is newer.
-  app_with_locale_list_ = std::move(app_with_locale_list);
+  app_with_locale_list_ = PopulateAppWithLocaleList(binary_pb);
+  if (base::FeatureList::IsEnabled(features::kAppDeduplicationService)) {
+    duplicated_apps_map_ = PopulateDuplicatedAppsMap();
+  }
   data_dir_ = install_dir;
   OnAppDataUpdated();
 }
@@ -48,7 +79,7 @@
 }
 
 void AppProvisioningDataManager::OnAppDataUpdated() {
-  if (!app_with_locale_list_) {
+  if (!app_with_locale_list_ && !duplicated_apps_map_) {
     return;
   }
   for (auto& observer : observers_) {
@@ -58,7 +89,7 @@
 
 void AppProvisioningDataManager::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
-  if (app_with_locale_list_) {
+  if (app_with_locale_list_ || duplicated_apps_map_) {
     NotifyObserver(*observer);
   }
 }
@@ -68,7 +99,16 @@
 }
 
 void AppProvisioningDataManager::NotifyObserver(Observer& observer) {
-  observer.OnAppWithLocaleListUpdated(*app_with_locale_list_.get());
+  // TODO(b/221173736): Add version check so that only notify observer when new
+  // version is available.
+  if (app_with_locale_list_) {
+    observer.OnAppWithLocaleListUpdated(*app_with_locale_list_.get());
+  }
+  // TODO(b/238394602): Add version check so that only notify observer when new
+  // version is available.
+  if (duplicated_apps_map_) {
+    observer.OnDuplicatedAppsMapUpdated(*duplicated_apps_map_.get());
+  }
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
index 2eeb72c..8b20240 100644
--- a/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
+++ b/chrome/browser/apps/app_provisioning_service/app_provisioning_data_manager.h
@@ -26,6 +26,8 @@
    public:
     virtual void OnAppWithLocaleListUpdated(
         const proto::AppWithLocaleList& app_with_locale_list) {}
+    virtual void OnDuplicatedAppsMapUpdated(
+        const proto::DuplicatedAppsMap& duplicated_apps_map) {}
   };
 
   static AppProvisioningDataManager* Get();
@@ -62,6 +64,7 @@
 
   // The latest app data. Starts out as null.
   std::unique_ptr<proto::AppWithLocaleList> app_with_locale_list_;
+  std::unique_ptr<proto::DuplicatedAppsMap> duplicated_apps_map_;
 
   base::ObserverList<Observer> observers_;
 
diff --git a/chrome/browser/apps/app_provisioning_service/proto/app_data.proto b/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
index 2232b0b..51c2aa8 100644
--- a/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
+++ b/chrome/browser/apps/app_provisioning_service/proto/app_data.proto
@@ -51,3 +51,14 @@
   optional string icon_path = 1;
   optional bool is_masking_allowed = 2;
 }
+
+// A group of apps that considered as duplicated. This group will also include
+// meta data for duplication in the future, e.g. confidence, etc.
+message DuplicateGroup {
+  repeated App apps = 1;
+}
+
+// A map for duplicate groups, each group is defined by a string key.
+message DuplicatedAppsMap {
+  map<string, DuplicateGroup> duplicated_apps_map = 1;
+}
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h
index 8704835f..d2f2d65 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.h
+++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_H_
 
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/apps/app_service/app_service_proxy_forward.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_forward.h"  // IWYU pragma: export
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"  // IWYU pragma: export
 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "chrome/browser/apps/app_service/app_service_proxy_lacros.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_lacros.h"  // IWYU pragma: export
 #else
-#include "chrome/browser/apps/app_service/app_service_proxy_desktop.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_desktop.h"  // IWYU pragma: export
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #endif  // CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_H_
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index c87b99e..81a4d0b 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -662,6 +662,8 @@
   }
   // Set the pref here, after we first successfully install something
   profile_->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true);
+  // Register penguin so it will show in Terminal even on failure (b/221771751).
+  AddNewLxdContainerToPrefs(profile_, DefaultContainerId());
 
   // Allow concierge to choose an appropriate disk image size.
   int64_t disk_size_bytes = requests_[0].options.disk_size_bytes.value_or(0);
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks.cc b/chrome/browser/ash/file_manager/app_service_file_tasks.cc
index 2be99588..5e71982b 100644
--- a/chrome/browser/ash/file_manager/app_service_file_tasks.cc
+++ b/chrome/browser/ash/file_manager/app_service_file_tasks.cc
@@ -98,6 +98,19 @@
   return true;
 }
 
+Profile* GetProfileWithAppService(Profile* profile) {
+  if (apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
+    return profile;
+  } else {
+    if (profile->IsOffTheRecord()) {
+      return profile->GetOriginalProfile();
+    } else {
+      LOG(WARNING) << "Unexpected profile type";
+      return nullptr;
+    }
+  }
+}
+
 void FindAppServiceTasks(Profile* profile,
                          const std::vector<extensions::EntryInfo>& entries,
                          const std::vector<GURL>& file_urls,
@@ -129,18 +142,12 @@
   // App Service doesn't exist in Incognito mode but we still want to find
   // handlers to open a download from its notification from Incognito mode. Use
   // the base profile in these cases (see crbug.com/1111695).
-  Profile* maybe_original_profile = profile;
-  if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
-    if (profile->IsOffTheRecord()) {
-      maybe_original_profile = profile->GetOriginalProfile();
-    } else {
-      LOG(WARNING) << "Unexpected profile type";
-      return;
-    }
+  Profile* profile_with_app_service = GetProfileWithAppService(profile);
+  if (!profile_with_app_service) {
+    return;
   }
-
   apps::AppServiceProxy* proxy =
-      apps::AppServiceProxyFactory::GetForProfile(maybe_original_profile);
+      apps::AppServiceProxyFactory::GetForProfile(profile_with_app_service);
 
   std::vector<apps::IntentFilePtr> intent_files;
   intent_files.reserve(entries.size());
@@ -188,7 +195,7 @@
       // TODO(1240018): Remove when this feature is fully launched. This check
       // will not work for lacros web apps.
       web_app::WebAppProvider* provider =
-          web_app::WebAppProvider::GetDeprecated(maybe_original_profile);
+          web_app::WebAppProvider::GetDeprecated(profile_with_app_service);
       web_app::OsIntegrationManager& os_integration_manager =
           provider->os_integration_manager();
       if (!os_integration_manager.IsFileHandlingAPIAvailable(
@@ -201,7 +208,7 @@
       if (profile->IsOffTheRecord() &&
           !extensions::util::IsIncognitoEnabled(launch_entry.app_id, profile))
         continue;
-      if (!FileHandlerIsEnabled(maybe_original_profile,
+      if (!FileHandlerIsEnabled(profile_with_app_service,
                                 launch_entry.activity_name))
         continue;
     }
@@ -234,16 +241,12 @@
   // launched (ie. default handler to open a download from its
   // notification) from Incognito mode. Use the base profile in these
   // cases (see crbug.com/1111695).
-  if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
-    if (profile->IsOffTheRecord()) {
-      profile = profile->GetOriginalProfile();
-    } else {
-      LOG(WARNING) << "Unexpected profile type";
-      std::move(done).Run(
-          extensions::api::file_manager_private::TASK_RESULT_FAILED,
-          "Unexpected profile type");
-      return;
-    }
+  Profile* profile_with_app_service = GetProfileWithAppService(profile);
+  if (!profile_with_app_service) {
+    std::move(done).Run(
+        extensions::api::file_manager_private::TASK_RESULT_FAILED,
+        "Unexpected profile type");
+    return;
   }
 
   std::vector<GURL> file_urls;
@@ -272,55 +275,57 @@
   intent->activity_name = task.action_id;
 
   if (base::FeatureList::IsEnabled(apps::kAppServiceLaunchWithoutMojom)) {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->LaunchAppWithIntent(
-        task.app_id, ui::EF_NONE, std::move(intent),
-        apps::LaunchSource::kFromFileManager,
-        std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId),
-        base::BindOnce(
-            [](FileTaskFinishedCallback done, TaskType task_type,
-               bool success) {
-              if (!success) {
-                std::move(done).Run(
-                    extensions::api::file_manager_private::TASK_RESULT_FAILED,
-                    "");
-              } else if (task_type == TASK_TYPE_WEB_APP) {
-                // TODO(benwells): return the correct code here, depending on
-                // how the app will be opened in multiprofile.
-                std::move(done).Run(
-                    extensions::api::file_manager_private::TASK_RESULT_OPENED,
-                    "");
-              } else {
-                std::move(done).Run(extensions::api::file_manager_private::
-                                        TASK_RESULT_MESSAGE_SENT,
-                                    "");
-              }
-            },
-            std::move(done), task.task_type));
+    apps::AppServiceProxyFactory::GetForProfile(profile_with_app_service)
+        ->LaunchAppWithIntent(
+            task.app_id, ui::EF_NONE, std::move(intent),
+            apps::LaunchSource::kFromFileManager,
+            std::make_unique<apps::WindowInfo>(display::kDefaultDisplayId),
+            base::BindOnce(
+                [](FileTaskFinishedCallback done, TaskType task_type,
+                   bool success) {
+                  if (!success) {
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_FAILED,
+                                        "");
+                  } else if (task_type == TASK_TYPE_WEB_APP) {
+                    // TODO(benwells): return the correct code here, depending
+                    // on how the app will be opened in multiprofile.
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_OPENED,
+                                        "");
+                  } else {
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_MESSAGE_SENT,
+                                        "");
+                  }
+                },
+                std::move(done), task.task_type));
   } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile)->LaunchAppWithIntent(
-        task.app_id, ui::EF_NONE, apps::ConvertIntentToMojomIntent(intent),
-        apps::mojom::LaunchSource::kFromFileManager,
-        apps::MakeWindowInfo(display::kDefaultDisplayId),
-        base::BindOnce(
-            [](FileTaskFinishedCallback done, TaskType task_type,
-               bool success) {
-              if (!success) {
-                std::move(done).Run(
-                    extensions::api::file_manager_private::TASK_RESULT_FAILED,
-                    "");
-              } else if (task_type == TASK_TYPE_WEB_APP) {
-                // TODO(benwells): return the correct code here, depending on
-                // how the app will be opened in multiprofile.
-                std::move(done).Run(
-                    extensions::api::file_manager_private::TASK_RESULT_OPENED,
-                    "");
-              } else {
-                std::move(done).Run(extensions::api::file_manager_private::
-                                        TASK_RESULT_MESSAGE_SENT,
-                                    "");
-              }
-            },
-            std::move(done), task.task_type));
+    apps::AppServiceProxyFactory::GetForProfile(profile_with_app_service)
+        ->LaunchAppWithIntent(
+            task.app_id, ui::EF_NONE, apps::ConvertIntentToMojomIntent(intent),
+            apps::mojom::LaunchSource::kFromFileManager,
+            apps::MakeWindowInfo(display::kDefaultDisplayId),
+            base::BindOnce(
+                [](FileTaskFinishedCallback done, TaskType task_type,
+                   bool success) {
+                  if (!success) {
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_FAILED,
+                                        "");
+                  } else if (task_type == TASK_TYPE_WEB_APP) {
+                    // TODO(benwells): return the correct code here, depending
+                    // on how the app will be opened in multiprofile.
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_OPENED,
+                                        "");
+                  } else {
+                    std::move(done).Run(extensions::api::file_manager_private::
+                                            TASK_RESULT_MESSAGE_SENT,
+                                        "");
+                  }
+                },
+                std::move(done), task.task_type));
   }
 }
 
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks.h b/chrome/browser/ash/file_manager/app_service_file_tasks.h
index a8c7231..ace5d07 100644
--- a/chrome/browser/ash/file_manager/app_service_file_tasks.h
+++ b/chrome/browser/ash/file_manager/app_service_file_tasks.h
@@ -28,6 +28,13 @@
 // import-crostini-image can be disabled at runtime by enterprise policy.
 bool FileHandlerIsEnabled(Profile* profile, const std::string& file_handler_id);
 
+// Returns a profile that has App Service available. App Service doesn't exist
+// in Incognito mode, so when the user opens a file from the downloads page
+// within an Incognito browser, we will use the base profile instead. If neither
+// the given profile nor the base profile have access to an available App
+// Service, we return a nullptr.
+Profile* GetProfileWithAppService(Profile* profile);
+
 // Finds the app services tasks that can handle |entries|, appends them to
 // |result_list|, and calls back to |callback|.
 // Only support sharing at the moment.
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index 223f66b..17943d7 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -339,7 +339,7 @@
   if (!disabled_actions.empty())
     RemoveFileManagerInternalActions(disabled_actions, result_list.get());
 
-  ChooseAndSetDefaultTask(*profile->GetPrefs(), entries, result_list.get());
+  ChooseAndSetDefaultTask(profile, entries, result_list.get());
   std::move(callback).Run(std::move(result_list));
 }
 
@@ -494,14 +494,38 @@
          action_id == kActionIdHandleOffice;
 }
 
-void UpdateDefaultTask(PrefService* pref_service,
+void UpdateDefaultTask(Profile* profile,
                        const TaskDescriptor& task_descriptor,
                        const std::set<std::string>& suffixes,
                        const std::set<std::string>& mime_types) {
+  PrefService* pref_service = profile->GetPrefs();
   if (!pref_service)
     return;
 
   std::string task_id = TaskDescriptorToId(task_descriptor);
+  if (ash::features::ShouldArcAndGuestOsFileTasksUseAppService() &&
+      task_descriptor.task_type == TASK_TYPE_ARC_APP) {
+    // Task IDs for Android apps are stored in a legacy format (app id:
+    // "<package>/<activity>", task id: "view"). For ARC app task descriptors
+    // (which use app id: "<app service id>", action id: "<activity>"), we
+    // generate Task IDs in the legacy format.
+    std::string package;
+    DCHECK(
+        apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile));
+    apps::AppServiceProxy* proxy =
+        apps::AppServiceProxyFactory::GetForProfile(profile);
+    if (proxy) {
+      proxy->AppRegistryCache().ForOneApp(
+          task_descriptor.app_id, [&package](const apps::AppUpdate& update) {
+            package = update.PublisherId();
+          });
+    }
+    if (!package.empty()) {
+      std::string new_app_id = package + "/" + task_descriptor.action_id;
+      task_id = MakeTaskID(new_app_id, TASK_TYPE_ARC_APP, kActionIdView);
+    }
+  }
+
   if (!mime_types.empty()) {
     DictionaryPrefUpdate mime_type_pref(pref_service,
                                         prefs::kDefaultTasksByMimeType);
@@ -804,7 +828,7 @@
   }
 }
 
-void ChooseAndSetDefaultTask(const PrefService& pref_service,
+void ChooseAndSetDefaultTask(Profile* profile,
                              const std::vector<extensions::EntryInfo>& entries,
                              std::vector<FullTaskDescriptor>* tasks) {
   // Collect the default tasks from the preferences into a set.
@@ -813,9 +837,42 @@
     const base::FilePath& file_path = entry.path;
     const std::string& mime_type = entry.mime_type;
     TaskDescriptor default_task;
-    if (file_tasks::GetDefaultTaskFromPrefs(
-            pref_service, mime_type, file_path.Extension(), &default_task)) {
+    if (file_tasks::GetDefaultTaskFromPrefs(*profile->GetPrefs(), mime_type,
+                                            file_path.Extension(),
+                                            &default_task)) {
       default_tasks.insert(default_task);
+      if (ash::features::ShouldArcAndGuestOsFileTasksUseAppService() &&
+          default_task.task_type == TASK_TYPE_ARC_APP) {
+        // Default preference Task Descriptors for Android apps are stored in a
+        // legacy format (app id: "<package>/<activity>", action id: "view"). To
+        // match against ARC app task descriptors (which use app id: "<app
+        // service id>", action id: "<activity>"), we translate the default Task
+        // Descriptors into the new format.
+        std::vector<std::string> app_id_info =
+            base::SplitString(default_task.app_id, "/", base::KEEP_WHITESPACE,
+                              base::SPLIT_WANT_NONEMPTY);
+        if (app_id_info.size() != 2) {
+          continue;
+        }
+        const std::string& package = app_id_info[0];
+        const std::string& activity = app_id_info[1];
+
+        Profile* profile_with_app_service = GetProfileWithAppService(profile);
+        if (profile_with_app_service) {
+          // Add possible alternative forms of this task descriptor to our list
+          // of default tasks.
+          apps::AppServiceProxyFactory::GetForProfile(profile_with_app_service)
+              ->AppRegistryCache()
+              .ForEachApp([&default_tasks, package,
+                           activity](const apps::AppUpdate& update) {
+                if (update.PublisherId() == package) {
+                  TaskDescriptor alternate_default_task(
+                      update.AppId(), TASK_TYPE_ARC_APP, activity);
+                  default_tasks.insert(alternate_default_task);
+                }
+              });
+        }
+      }
     }
   }
 
diff --git a/chrome/browser/ash/file_manager/file_tasks.h b/chrome/browser/ash/file_manager/file_tasks.h
index abd4a02..d2cf0216 100644
--- a/chrome/browser/ash/file_manager/file_tasks.h
+++ b/chrome/browser/ash/file_manager/file_tasks.h
@@ -231,7 +231,7 @@
 
 // Update the default file handler for the given sets of suffixes and MIME
 // types.
-void UpdateDefaultTask(PrefService* pref_service,
+void UpdateDefaultTask(Profile* profile,
                        const TaskDescriptor& task_descriptor,
                        const std::set<std::string>& suffixes,
                        const std::set<std::string>& mime_types);
@@ -315,7 +315,7 @@
 // Chooses the default task in |tasks| and sets it as default, if the default
 // task is found (i.e. the default task may not exist in |tasks|). No tasks
 // should be set as default before calling this function.
-void ChooseAndSetDefaultTask(const PrefService& pref_service,
+void ChooseAndSetDefaultTask(Profile* profile,
                              const std::vector<extensions::EntryInfo>& entries,
                              std::vector<FullTaskDescriptor>* tasks);
 
diff --git a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
index 6470f43..f4e908a0 100644
--- a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
@@ -390,7 +390,7 @@
   TestExpectationsAgainstDefaultTasks({{"tiff", kMediaAppId}});
 
   UpdateDefaultTask(
-      profile->GetPrefs(),
+      profile,
       TaskDescriptor(extension->id(), StringToTaskType("app"), "tiffAction"),
       {"tiff"}, {"image/tiff"});
   if (profile_type() == TestProfileType::kIncognito) {
diff --git a/chrome/browser/ash/file_manager/file_tasks_unittest.cc b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
index d024ce3..150fa56 100644
--- a/chrome/browser/ash/file_manager/file_tasks_unittest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_unittest.cc
@@ -18,6 +18,9 @@
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/values.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/app_service_test.h"
 #include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/browser/ash/crostini/fake_crostini_features.h"
@@ -30,6 +33,7 @@
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
@@ -38,8 +42,11 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/features.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
 #include "components/services/app_service/public/cpp/file_handler_info.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/browser/entry_info.h"
 #include "extensions/browser/extension_prefs.h"
@@ -58,31 +65,6 @@
 
 namespace file_manager {
 namespace file_tasks {
-namespace {
-
-// Registers the default task preferences. Used for testing
-// ChooseAndSetDefaultTask().
-void RegisterDefaultTaskPreferences(TestingPrefServiceSimple* pref_service) {
-  DCHECK(pref_service);
-
-  pref_service->registry()->RegisterDictionaryPref(
-      prefs::kDefaultTasksByMimeType);
-  pref_service->registry()->RegisterDictionaryPref(
-      prefs::kDefaultTasksBySuffix);
-}
-
-// Updates the default task preferences per the given dictionary values. Used
-// for testing ChooseAndSetDefaultTask.
-void UpdateDefaultTaskPreferences(TestingPrefServiceSimple* pref_service,
-                                  const base::DictionaryValue& mime_types,
-                                  const base::DictionaryValue& suffixes) {
-  DCHECK(pref_service);
-
-  pref_service->Set(prefs::kDefaultTasksByMimeType, mime_types);
-  pref_service->Set(prefs::kDefaultTasksBySuffix, suffixes);
-}
-
-}  // namespace
 
 TEST(FileManagerFileTasksTest, FullTaskDescriptor_WithIconAndDefault) {
   FullTaskDescriptor full_descriptor(
@@ -170,227 +152,6 @@
   ASSERT_TRUE(base::Contains(tasks, task_3));
 }
 
-// Test that the right task is chosen from multiple choices per mime types
-// and file extensions.
-TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_MultipleTasks) {
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-
-  // Text.app and Nice.app were found for "foo.txt".
-  TaskDescriptor text_app_task("text-app-id",
-                               TASK_TYPE_FILE_HANDLER,
-                               "action-id");
-  TaskDescriptor nice_app_task("nice-app-id",
-                               TASK_TYPE_FILE_HANDLER,
-                               "action-id");
-  std::vector<FullTaskDescriptor> tasks;
-  tasks.emplace_back(
-      text_app_task, "Text.app", Verb::VERB_OPEN_WITH,
-      GURL("http://example.com/text_app.png"), false /* is_default */,
-      false /* is_generic_file_handler */, false /* is_file_extension_match */);
-  tasks.emplace_back(
-      nice_app_task, "Nice.app", Verb::VERB_ADD_TO,
-      GURL("http://example.com/nice_app.png"), false /* is_default */,
-      false /* is_generic_file_handler */, false /* is_file_extension_match */);
-  std::vector<extensions::EntryInfo> entries;
-  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
-                       false);
-
-  // None of them should be chosen as default, as nothing is set in the
-  // preferences.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_FALSE(tasks[0].is_default);
-  EXPECT_FALSE(tasks[1].is_default);
-
-  // Set Text.app as default for "text/plain" in the preferences.
-  base::DictionaryValue empty;
-  base::DictionaryValue mime_types;
-  mime_types.SetKey("text/plain",
-                    base::Value(TaskDescriptorToId(text_app_task)));
-  UpdateDefaultTaskPreferences(&pref_service, mime_types, empty);
-
-  // Text.app should be chosen as default.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_TRUE(tasks[0].is_default);
-  EXPECT_FALSE(tasks[1].is_default);
-
-  // Change it back to non-default for testing further.
-  tasks[0].is_default = false;
-
-  // Clear the preferences and make sure none of them are default.
-  UpdateDefaultTaskPreferences(&pref_service, empty, empty);
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_FALSE(tasks[0].is_default);
-  EXPECT_FALSE(tasks[1].is_default);
-
-  // Set Nice.app as default for ".txt" in the preferences.
-  base::DictionaryValue suffixes;
-  suffixes.SetKey(".txt", base::Value(TaskDescriptorToId(nice_app_task)));
-  UpdateDefaultTaskPreferences(&pref_service, empty, suffixes);
-
-  // Now Nice.app should be chosen as default.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_FALSE(tasks[0].is_default);
-  EXPECT_TRUE(tasks[1].is_default);
-}
-
-// Test that internal file browser handler of the Files app is chosen as
-// default even if nothing is set in the preferences.
-TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackFileBrowser) {
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-
-  // The internal file browser handler of the Files app was found for "foo.txt".
-  TaskDescriptor files_app_task(kFileManagerAppId,
-                                TASK_TYPE_FILE_BROWSER_HANDLER,
-                                "view-in-browser");
-  std::vector<FullTaskDescriptor> tasks;
-  tasks.emplace_back(
-      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
-      GURL("http://example.com/some_icon.png"), false /* is_default */,
-      false /* is_generic_file_handler */, false /* is_file_extension_match */);
-  std::vector<extensions::EntryInfo> entries;
-  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
-                       false);
-
-  // The internal file browser handler should be chosen as default, as it's a
-  // fallback file browser handler.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_TRUE(tasks[0].is_default);
-}
-
-// Test that Text.app is chosen as default instead of the Files app
-// even if nothing is set in the preferences.
-TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackTextApp) {
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-
-  // Define the browser handler of the Files app for "foo.txt".
-  TaskDescriptor files_app_task(
-      kFileManagerAppId, TASK_TYPE_FILE_BROWSER_HANDLER, "view-in-browser");
-  // Define the text editor app for "foo.txt".
-  TaskDescriptor text_app_task(kTextEditorAppId, TASK_TYPE_FILE_HANDLER,
-                               "Text");
-  std::vector<FullTaskDescriptor> tasks;
-  tasks.emplace_back(
-      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
-      GURL("http://example.com/some_icon.png"), false /* is_default */,
-      false /* is_generic_file_handler */, false /* is_file_extension_match */);
-  tasks.emplace_back(
-      text_app_task, "Text", Verb::VERB_OPEN_WITH,
-      GURL("chrome://extension-icon/mmfbcljfglbokpmkimbfghdkjmjhdgbg/16/1"),
-      false /* is_default */, false /* is_generic_file_handler */,
-      false /* is_file_extension_match */);
-  std::vector<extensions::EntryInfo> entries;
-  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
-                       false);
-
-  // The text editor app should be chosen as default, as it's a fallback file
-  // browser handler.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_TRUE(tasks[1].is_default);
-}
-
-// Test that browser is chosen as default for HTML files instead of the Text
-// app even if nothing is set in the preferences.
-TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackHtmlTextApp) {
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-
-  // Define the browser handler of the Files app for "foo.html".
-  TaskDescriptor files_app_task(
-      kFileManagerAppId, TASK_TYPE_FILE_BROWSER_HANDLER, "view-in-browser");
-  // Define the text editor app for "foo.html".
-  TaskDescriptor text_app_task(kTextEditorAppId, TASK_TYPE_FILE_HANDLER,
-                               "Text");
-  std::vector<FullTaskDescriptor> tasks;
-  tasks.emplace_back(
-      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
-      GURL("http://example.com/some_icon.png"), false /* is_default */,
-      false /* is_generic_file_handler */, false /* is_file_extension_match */);
-  tasks.emplace_back(
-      text_app_task, "Text", Verb::VERB_OPEN_WITH,
-      GURL("chrome://extension-icon/mmfbcljfglbokpmkimbfghdkjmjhdgbg/16/1"),
-      false /* is_default */, false /* is_generic_file_handler */,
-      false /* is_file_extension_match */);
-  std::vector<extensions::EntryInfo> entries;
-  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.html"), "text/html",
-                       false);
-
-  // The internal file browser handler should be chosen as default,
-  // as it's a fallback file browser handler.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_TRUE(tasks[0].is_default);
-}
-
-// Test that Office Editing is chosen as default even if nothing is set in the
-// preferences.
-TEST(FileManagerFileTasksTest, ChooseAndSetDefaultTask_FallbackOfficeEditing) {
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-
-  // The Office Editing app was found for "slides.pptx".
-  TaskDescriptor files_app_task(
-      extension_misc::kQuickOfficeComponentExtensionId, TASK_TYPE_FILE_HANDLER,
-      "Office Editing for Docs, Sheets & Slides");
-  std::vector<FullTaskDescriptor> tasks;
-  tasks.emplace_back(
-      files_app_task, "Office Editing for Docs, Sheets & Slides",
-      Verb::VERB_OPEN_WITH,
-      GURL("chrome://extension-icon/bpmcpldpdmajfigpchkicefoigmkfalc/32/1"),
-      false /* is_default */, false /* is_generic_file_handler */,
-      false /* is_file_extension_match */);
-  std::vector<extensions::EntryInfo> entries;
-  entries.emplace_back(base::FilePath::FromUTF8Unsafe("slides.pptx"), "",
-                       false);
-
-  // The Office Editing app should be chosen as default, as it's a fallback
-  // file browser handler.
-  ChooseAndSetDefaultTask(pref_service, entries, &tasks);
-  EXPECT_TRUE(tasks[0].is_default);
-}
-
-// Test that for changes of default app for PDF files, a metric is recorded.
-TEST(FileManagerFileTasksTest, UpdateDefaultTask_RecordsPdfDefaultAppChanges) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      ash::features::kMediaAppHandlesPdf};
-  TestingPrefServiceSimple pref_service;
-  RegisterDefaultTaskPreferences(&pref_service);
-  base::UserActionTester user_action_tester;
-
-  // Non-PDF file types are not recorded.
-  TaskDescriptor other_app_task("other-app-id", TASK_TYPE_FILE_HANDLER,
-                                "action-id");
-  UpdateDefaultTask(&pref_service, other_app_task, {".txt"}, {"text/plain"});
-  // Even if it's the Media App.
-  TaskDescriptor media_app_task(web_app::kMediaAppId, TASK_TYPE_FILE_HANDLER,
-                                "action-id");
-  UpdateDefaultTask(&pref_service, media_app_task, {"tiff"}, {"image/tiff"});
-
-  EXPECT_EQ(0, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
-  EXPECT_EQ(0, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
-
-  // PDF files are recorded.
-  UpdateDefaultTask(&pref_service, media_app_task, {".pdf"},
-                    {"application/pdf"});
-
-  EXPECT_EQ(1, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
-  EXPECT_EQ(0, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
-  user_action_tester.ResetCounts();
-
-  UpdateDefaultTask(&pref_service, other_app_task, {".pdf"},
-                    {"application/pdf"});
-
-  EXPECT_EQ(0, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
-  EXPECT_EQ(1, user_action_tester.GetActionCount(
-                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
-}
-
 // Test FileHandlerIsEnabled which returns whether a file handler should be
 // used.
 TEST(FileManagerFileTasksTest, FileHandlerIsEnabled) {
@@ -417,6 +178,329 @@
   EXPECT_TRUE(FileHandlerIsEnabled(&test_profile, test_id));
 }
 
+class FileManagerFileTaskPreferencesTest : public testing::Test {
+ public:
+  void SetUp() override {
+    TestingProfile::Builder profile_builder;
+    profile_ = profile_builder.Build();
+    app_service_test_.SetUp(profile_.get());
+    app_service_proxy_ =
+        apps::AppServiceProxyFactory::GetForProfile(profile_.get());
+    ASSERT_TRUE(app_service_proxy_);
+  }
+
+  // Updates the default task preferences per the given dictionary values. Used
+  // for testing ChooseAndSetDefaultTask.
+  void UpdateDefaultTaskPreferences(const base::DictionaryValue& mime_types,
+                                    const base::DictionaryValue& suffixes) {
+    profile_->GetTestingPrefService()->Set(prefs::kDefaultTasksByMimeType,
+                                           mime_types);
+    profile_->GetTestingPrefService()->Set(prefs::kDefaultTasksBySuffix,
+                                           suffixes);
+  }
+
+  void AddFakeAppToAppService(const std::string& app_id,
+                              const std::string& package_name,
+                              apps::AppType app_type) {
+    std::vector<apps::AppPtr> apps;
+    auto app = std::make_unique<apps::App>(app_type, app_id);
+    app->app_id = app_id;
+    app->app_type = app_type;
+    app->publisher_id = package_name;
+    app->readiness = apps::Readiness::kReady;
+    apps.push_back(std::move(app));
+    app_service_proxy_->AppRegistryCache().OnApps(
+        std::move(apps), app_type, false /* should_notify_initialized */);
+  }
+
+  TestingProfile* profile() { return profile_.get(); }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  std::unique_ptr<TestingProfile> profile_;
+  apps::AppServiceProxy* app_service_proxy_ = nullptr;
+  apps::AppServiceTest app_service_test_;
+};
+
+// Test that the right task is chosen from multiple choices per mime types
+// and file extensions.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefaultTask_MultipleTasks) {
+  // Text.app and Nice.app were found for "foo.txt".
+  TaskDescriptor text_app_task("text-app-id",
+                               TASK_TYPE_FILE_HANDLER,
+                               "action-id");
+  TaskDescriptor nice_app_task("nice-app-id",
+                               TASK_TYPE_FILE_HANDLER,
+                               "action-id");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      text_app_task, "Text.app", Verb::VERB_OPEN_WITH,
+      GURL("http://example.com/text_app.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  tasks.emplace_back(
+      nice_app_task, "Nice.app", Verb::VERB_ADD_TO,
+      GURL("http://example.com/nice_app.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
+                       false);
+
+  // None of them should be chosen as default, as nothing is set in the
+  // preferences.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_FALSE(tasks[0].is_default);
+  EXPECT_FALSE(tasks[1].is_default);
+
+  // Set Text.app as default for "text/plain" in the preferences.
+  base::DictionaryValue empty;
+  base::DictionaryValue mime_types;
+  mime_types.SetKey("text/plain",
+                    base::Value(TaskDescriptorToId(text_app_task)));
+  UpdateDefaultTaskPreferences(mime_types, empty);
+
+  // Text.app should be chosen as default.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_TRUE(tasks[0].is_default);
+  EXPECT_FALSE(tasks[1].is_default);
+
+  // Change it back to non-default for testing further.
+  tasks[0].is_default = false;
+
+  // Clear the preferences and make sure none of them are default.
+  UpdateDefaultTaskPreferences(empty, empty);
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_FALSE(tasks[0].is_default);
+  EXPECT_FALSE(tasks[1].is_default);
+
+  // Set Nice.app as default for ".txt" in the preferences.
+  base::DictionaryValue suffixes;
+  suffixes.SetKey(".txt", base::Value(TaskDescriptorToId(nice_app_task)));
+  UpdateDefaultTaskPreferences(empty, suffixes);
+
+  // Now Nice.app should be chosen as default.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_FALSE(tasks[0].is_default);
+  EXPECT_TRUE(tasks[1].is_default);
+}
+
+// Test that internal file browser handler of the Files app is chosen as
+// default even if nothing is set in the preferences.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefaultTask_FallbackFileBrowser) {
+  // The internal file browser handler of the Files app was found for
+  // "foo.txt".
+  TaskDescriptor files_app_task(kFileManagerAppId,
+                                TASK_TYPE_FILE_BROWSER_HANDLER,
+                                "view-in-browser");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
+      GURL("http://example.com/some_icon.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
+                       false);
+
+  // The internal file browser handler should be chosen as default, as it's a
+  // fallback file browser handler.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_TRUE(tasks[0].is_default);
+}
+
+// Test that Text.app is chosen as default instead of the Files app
+// even if nothing is set in the preferences.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefaultTask_FallbackTextApp) {
+  // Define the browser handler of the Files app for "foo.txt".
+  TaskDescriptor files_app_task(
+      kFileManagerAppId, TASK_TYPE_FILE_BROWSER_HANDLER, "view-in-browser");
+  // Define the text editor app for "foo.txt".
+  TaskDescriptor text_app_task(kTextEditorAppId, TASK_TYPE_FILE_HANDLER,
+                               "Text");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
+      GURL("http://example.com/some_icon.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  tasks.emplace_back(
+      text_app_task, "Text", Verb::VERB_OPEN_WITH,
+      GURL("chrome://extension-icon/mmfbcljfglbokpmkimbfghdkjmjhdgbg/16/1"),
+      false /* is_default */, false /* is_generic_file_handler */,
+      false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "text/plain",
+                       false);
+
+  // The text editor app should be chosen as default, as it's a fallback file
+  // browser handler.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_TRUE(tasks[1].is_default);
+}
+
+// Test that browser is chosen as default for HTML files instead of the Text
+// app even if nothing is set in the preferences.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefaultTask_FallbackHtmlTextApp) {
+  // Define the browser handler of the Files app for "foo.html".
+  TaskDescriptor files_app_task(
+      kFileManagerAppId, TASK_TYPE_FILE_BROWSER_HANDLER, "view-in-browser");
+  // Define the text editor app for "foo.html".
+  TaskDescriptor text_app_task(kTextEditorAppId, TASK_TYPE_FILE_HANDLER,
+                               "Text");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      files_app_task, "View in browser", Verb::VERB_OPEN_WITH,
+      GURL("http://example.com/some_icon.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  tasks.emplace_back(
+      text_app_task, "Text", Verb::VERB_OPEN_WITH,
+      GURL("chrome://extension-icon/mmfbcljfglbokpmkimbfghdkjmjhdgbg/16/1"),
+      false /* is_default */, false /* is_generic_file_handler */,
+      false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.html"), "text/html",
+                       false);
+
+  // The internal file browser handler should be chosen as default,
+  // as it's a fallback file browser handler.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_TRUE(tasks[0].is_default);
+}
+
+// Test that Office Editing is chosen as default even if nothing is set in the
+// preferences.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefaultTask_FallbackOfficeEditing) {
+  // The Office Editing app was found for "slides.pptx".
+  TaskDescriptor files_app_task(
+      extension_misc::kQuickOfficeComponentExtensionId, TASK_TYPE_FILE_HANDLER,
+      "Office Editing for Docs, Sheets & Slides");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      files_app_task, "Office Editing for Docs, Sheets & Slides",
+      Verb::VERB_OPEN_WITH,
+      GURL("chrome://extension-icon/bpmcpldpdmajfigpchkicefoigmkfalc/32/1"),
+      false /* is_default */, false /* is_generic_file_handler */,
+      false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("slides.pptx"), "",
+                       false);
+
+  // The Office Editing app should be chosen as default, as it's a fallback
+  // file browser handler.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  EXPECT_TRUE(tasks[0].is_default);
+}
+
+// Test that for changes of default app for PDF files, a metric is recorded.
+TEST_F(FileManagerFileTaskPreferencesTest,
+       UpdateDefaultTask_RecordsPdfDefaultAppChanges) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      ash::features::kMediaAppHandlesPdf};
+  base::UserActionTester user_action_tester;
+
+  // Non-PDF file types are not recorded.
+  TaskDescriptor other_app_task("other-app-id", TASK_TYPE_FILE_HANDLER,
+                                "action-id");
+  UpdateDefaultTask(profile(), other_app_task, {".txt"}, {"text/plain"});
+  // Even if it's the Media App.
+  TaskDescriptor media_app_task(web_app::kMediaAppId, TASK_TYPE_FILE_HANDLER,
+                                "action-id");
+  UpdateDefaultTask(profile(), media_app_task, {"tiff"}, {"image/tiff"});
+
+  EXPECT_EQ(0, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
+
+  // PDF files are recorded.
+  UpdateDefaultTask(profile(), media_app_task, {".pdf"}, {"application/pdf"});
+
+  EXPECT_EQ(1, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
+  EXPECT_EQ(0, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
+  user_action_tester.ResetCounts();
+
+  UpdateDefaultTask(profile(), other_app_task, {".pdf"}, {"application/pdf"});
+
+  EXPECT_EQ(0, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedTo"));
+  EXPECT_EQ(1, user_action_tester.GetActionCount(
+                   "MediaApp.PDF.DefaultApp.SwitchedAway"));
+}
+
+TEST_F(FileManagerFileTaskPreferencesTest,
+       ChooseAndSetDefault_MatchesWithAlternateAppServiceTaskDescriptorForm) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      ash::features::kArcAndGuestOsFileTasksUseAppService};
+
+  std::string package = "com.example.gallery";
+  std::string activity = "com.example.gallery.OpenActivity";
+  std::string app_id = "zabcdefg";
+  TaskType task_type = TASK_TYPE_ARC_APP;
+
+  AddFakeAppToAppService(app_id, package, apps::AppType::kArc);
+
+  // Set the default app preference.
+  std::string files_app_id = package + "/" + activity;
+  TaskDescriptor file_task(files_app_id, task_type, "view");
+  base::DictionaryValue mime_types;
+  mime_types.SetKey("image/png", base::Value(TaskDescriptorToId(file_task)));
+  UpdateDefaultTaskPreferences(mime_types, {});
+
+  // Create the file task descriptors to match against.
+  TaskDescriptor app_service_file_task(app_id, task_type, activity);
+  TaskDescriptor other_task("other", TASK_TYPE_FILE_BROWSER_HANDLER, "view");
+  std::vector<FullTaskDescriptor> tasks;
+  tasks.emplace_back(
+      app_service_file_task, "View Images", Verb::VERB_NONE,
+      GURL("http://example.com/some_icon.png"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  tasks.emplace_back(
+      other_task, "Other", Verb::VERB_NONE,
+      GURL("http://example.com/other.text"), false /* is_default */,
+      false /* is_generic_file_handler */, false /* is_file_extension_match */);
+  std::vector<extensions::EntryInfo> entries;
+  entries.emplace_back(base::FilePath::FromUTF8Unsafe("foo.txt"), "image/png",
+                       false);
+
+  // Check if the correct task matched against the default preference.
+  ChooseAndSetDefaultTask(profile(), entries, &tasks);
+  ASSERT_TRUE(tasks[0].is_default);
+  ASSERT_FALSE(tasks[1].is_default);
+}
+
+TEST_F(FileManagerFileTaskPreferencesTest,
+       UpdateDefaultTask_ConvertsArcAppServiceTaskDescriptorToStandardTaskId) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      ash::features::kArcAndGuestOsFileTasksUseAppService};
+
+  std::string package = "com.example.gallery";
+  std::string activity = "com.example.gallery.OpenActivity";
+  std::string app_id = "zabcdefg";
+  TaskType task_type = TASK_TYPE_ARC_APP;
+  std::string mime_type = "image/png";
+
+  AddFakeAppToAppService(app_id, package, apps::AppType::kArc);
+
+  // Update default task preferences with our task descriptor (which is in the
+  // format given from App Service file tasks).
+  TaskDescriptor app_service_file_task(app_id, task_type, activity);
+  UpdateDefaultTask(profile(), app_service_file_task, {}, {mime_type});
+
+  // Check that the saved default preference is in the right format.
+  std::string files_app_id = package + "/" + activity;
+  std::string files_task_id = files_app_id + "|arc|view";
+  const std::string* default_task_id =
+      profile()
+          ->GetTestingPrefService()
+          ->GetDictionary(prefs::kDefaultTasksByMimeType)
+          ->FindStringKey(mime_type);
+  ASSERT_EQ(*default_task_id, files_task_id);
+}
+
 // Test using the test extension system, which needs lots of setup.
 class FileManagerFileTasksComplexTest : public testing::Test {
  protected:
diff --git a/chrome/browser/ash/login/eula_browsertest.cc b/chrome/browser/ash/login/eula_browsertest.cc
index 8ddca6a5..b5ff732 100644
--- a/chrome/browser/ash/login/eula_browsertest.cc
+++ b/chrome/browser/ash/login/eula_browsertest.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/installer/util/google_update_settings.h"
@@ -58,6 +59,7 @@
 const test::UIPath kAdditionalTermsLink = {"oobe-eula-md", "additionalTerms"};
 const test::UIPath kAdditionalTermsDialog = {"oobe-eula-md", "additionalToS"};
 const test::UIPath kLearnMoreLink = {"oobe-eula-md", "learnMore"};
+const test::UIPath kBackButton = {"oobe-eula-md", "backButton"};
 
 const char kRemoraRequisition[] = "remora";
 
@@ -342,5 +344,11 @@
   EXPECT_FALSE(GetGoogleCollectStatsConsent());
 }
 
+IN_PROC_BROWSER_TEST_F(EulaTest, ClickBack) {
+  ShowEulaScreen();
+  test::OobeJS().ClickOnPath(kBackButton);
+  OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/chrome/browser/ash/login/screens/eula_screen.cc b/chrome/browser/ash/login/screens/eula_screen.cc
index 7a638958..115df0a 100644
--- a/chrome/browser/ash/login/screens/eula_screen.cc
+++ b/chrome/browser/ash/login/screens/eula_screen.cc
@@ -93,6 +93,7 @@
     case Result::ACCEPTED_WITHOUT_USAGE_STATS_REPORTING:
       return "AcceptedWithoutStats";
     case Result::BACK:
+    case Result::BACK_DEMO_MODE:
       return "Back";
     case Result::ALREADY_ACCEPTED:
     case Result::ALREADY_ACCEPTED_DEMO_MODE:
@@ -203,7 +204,10 @@
                            ? Result::ACCEPTED_WITH_USAGE_STATS_REPORTING
                            : Result::ACCEPTED_WITHOUT_USAGE_STATS_REPORTING);
   } else if (action_id == kUserActionBackButtonClicked) {
-    exit_callback_.Run(Result::BACK);
+    const auto* const demo_setup_controller =
+        WizardController::default_controller()->demo_setup_controller();
+    exit_callback_.Run(demo_setup_controller ? Result::BACK_DEMO_MODE
+                                             : Result::BACK);
   }
 }
 
diff --git a/chrome/browser/ash/login/screens/eula_screen.h b/chrome/browser/ash/login/screens/eula_screen.h
index 08d3131..45d58d6 100644
--- a/chrome/browser/ash/login/screens/eula_screen.h
+++ b/chrome/browser/ash/login/screens/eula_screen.h
@@ -28,8 +28,11 @@
     ALREADY_ACCEPTED,
     // Eula already accepted, skip screen (demo mode)
     ALREADY_ACCEPTED_DEMO_MODE,
-    // The usage did not accept EULA - they clicked back button instead.
+    // The user did not accept EULA - they clicked back button instead.
     BACK,
+    // The user did not accept EULA - they clicked back button instead (demo
+    // mode).
+    BACK_DEMO_MODE,
     // Eula screen is skipped.
     NOT_APPLICABLE,
   };
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index d064df5..38e7be7 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -1449,6 +1449,11 @@
       OnEulaAccepted(false /*usage_statistics_reporting_enabled*/);
       break;
     case EulaScreen::Result::BACK:
+      DCHECK(!demo_setup_controller_);
+      ShowNetworkScreen();
+      break;
+    case EulaScreen::Result::BACK_DEMO_MODE:
+      DCHECK(demo_setup_controller_);
       ShowDemoModePreferencesScreen();
       break;
   }
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 3d0fe02ed..cbc7b5f 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -993,11 +993,11 @@
   mock_network_screen_->ExitScreen(NetworkScreen::Result::CONNECTED_REGULAR);
 
   CheckCurrentScreen(EulaView::kScreenId);
-  EXPECT_CALL(*mock_demo_preferences_screen_, ShowImpl()).Times(1);
+  EXPECT_CALL(*mock_network_screen_, ShowImpl()).Times(1);
   EXPECT_CALL(*mock_eula_screen_, HideImpl()).Times(1);
   mock_eula_screen_->ExitScreen(EulaScreen::Result::BACK);
 
-  CheckCurrentScreen(MockDemoPreferencesScreenView::kScreenId);
+  CheckCurrentScreen(NetworkScreenView::kScreenId);
 }
 
 IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest,
@@ -2770,7 +2770,7 @@
   EXPECT_CALL(*mock_eula_screen_, HideImpl()).Times(1);
   EXPECT_CALL(*mock_demo_preferences_screen_, ShowImpl()).Times(1);
 
-  mock_eula_screen_->ExitScreen(EulaScreen::Result::BACK);
+  mock_eula_screen_->ExitScreen(EulaScreen::Result::BACK_DEMO_MODE);
 
   CheckCurrentScreen(DemoPreferencesScreenView::kScreenId);
   EXPECT_TRUE(DemoSetupController::IsOobeDemoSetupFlowInProgress());
diff --git a/chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.cc b/chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.cc
index 454ab7e..8fe09398 100644
--- a/chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.cc
+++ b/chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.cc
@@ -41,6 +41,7 @@
 
 RebootNotificationsScheduler::~RebootNotificationsScheduler() {
   DCHECK_EQ(instance, this);
+  observation_.Reset();
   RebootNotificationsScheduler::SetInstance(nullptr);
 }
 
diff --git a/chrome/browser/chrome_content_browser_client_binder_policies.cc b/chrome/browser/chrome_content_browser_client_binder_policies.cc
index 4485c62..0b55a3f0 100644
--- a/chrome/browser/chrome_content_browser_client_binder_policies.cc
+++ b/chrome/browser/chrome_content_browser_client_binder_policies.cc
@@ -37,10 +37,10 @@
       .SetAssociatedPolicy<subresource_filter::mojom::SubresourceFilterHost>(
           content::MojoBinderAssociatedPolicy::kGrant);
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-  // TODO(https://crbug.com/1278141): Revisit this decision after Prerender2
-  // support desktops.
-  // TODO(https://crbug.com/1259007): Introduce kExperimentalGrant and
-  // replace kGrant with kExperimentalGrant.
+  // LocalFrameHost supports content scripts related APIs, which are
+  // RequestScriptInjectionPermission, GetInstallState, SendRequestIPC, and
+  // notifying CSS selector updates. These APIs are used by Chrome Extensions
+  // under proper permission managements beyond the page boundaries.
   if (blink::features::IsPrerender2Enabled()) {
     policy_map.SetAssociatedPolicy<extensions::mojom::LocalFrameHost>(
         content::MojoBinderAssociatedPolicy::kGrant);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 7d305ff..2d6b094 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -315,6 +315,7 @@
     "//chromeos/ash/components/network/portal_detector",
     "//chromeos/ash/components/oobe_quick_start",
     "//chromeos/ash/components/scanning",
+    "//chromeos/ash/components/string_matching",
     "//chromeos/ash/services/assistant:lib",
     "//chromeos/ash/services/assistant/public/cpp",
     "//chromeos/ash/services/cros_healthd/private/cpp",
@@ -332,7 +333,6 @@
     "//chromeos/components/sensors:buildflags",
     "//chromeos/components/sensors/mojom",
     "//chromeos/components/sharesheet:constants",
-    "//chromeos/components/string_matching",
     "//chromeos/components/sync_wifi",
     "//chromeos/crosapi/cpp",
     "//chromeos/crosapi/mojom",
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index 383d431..2591219 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -1512,18 +1512,17 @@
     return;
   }
 
-  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+  base::Value::Dict result;
   for (const auto& hash : hashes) {
-    result->SetKey(hash, base::ListValue());
+    result.Set(hash, base::Value(base::Value::List()));
   }
 
   for (const auto& hashAndPath : search_results) {
-    DCHECK(result->FindKey(hashAndPath.hash));
-    base::ListValue* list;
-    result->GetListWithoutPathExpansion(hashAndPath.hash, &list);
+    base::Value::List* list = result.FindList(hashAndPath.hash);
+    DCHECK(list);
     list->Append(hashAndPath.path.value());
   }
-  Respond(OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
+  Respond(OneArgument(base::Value(std::move(result))));
 }
 
 FileManagerPrivateSearchFilesFunction::FileManagerPrivateSearchFilesFunction() =
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
index 8ff64deeb..ef7eca85b 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
@@ -269,8 +269,8 @@
   file_manager::file_tasks::TaskDescriptor descriptor(
       params->descriptor.app_id, task_type, params->descriptor.action_id);
 
-  file_manager::file_tasks::UpdateDefaultTask(profile->GetPrefs(), descriptor,
-                                              suffixes, mime_types);
+  file_manager::file_tasks::UpdateDefaultTask(profile, descriptor, suffixes,
+                                              mime_types);
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
index 654bb948..b13be45 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
@@ -90,6 +90,87 @@
       GetDlpHistogramPrefix() + dlp::kDlpPolicyPresentUMA, false, 1);
 }
 
+TEST_F(DlpRulesManagerImplTest, UnknownRestriction) {
+  base::Value rules(base::Value::Type::LIST);
+
+  base::Value src_urls(base::Value::Type::LIST);
+  src_urls.Append(kExampleUrl);
+
+  base::Value dst_urls(base::Value::Type::LIST);
+  dst_urls.Append(kWildCardMatching);
+
+  base::Value restrictions(base::Value::Type::LIST);
+  restrictions.Append(dlp_test_util::CreateRestrictionWithLevel(
+      "Wrong restriction", dlp::kBlockLevel));
+
+  rules.Append(dlp_test_util::CreateRule(
+      "rule #1", "Unknown", std::move(src_urls), std::move(dst_urls),
+      /*dst_components=*/base::Value(base::Value::Type::LIST),
+      std::move(restrictions)));
+
+  UpdatePolicyPref(std::move(rules));
+  histogram_tester_.ExpectBucketCount(
+      "Enterprise.Dlp.RestrictionConfigured",
+      DlpRulesManager::Restriction::kUnknownRestriction, 0);
+}
+
+TEST_F(DlpRulesManagerImplTest, UnknownComponent) {
+  base::Value rules(base::Value::Type::LIST);
+
+  base::Value src_urls(base::Value::Type::LIST);
+  src_urls.Append(kExampleUrl);
+
+  base::Value dst_components(base::Value::Type::LIST);
+  dst_components.Append("Wrong component");
+
+  base::Value restrictions(base::Value::Type::LIST);
+  restrictions.Append(dlp_test_util::CreateRestrictionWithLevel(
+      dlp::kClipboardRestriction, dlp::kBlockLevel));
+
+  rules.Append(dlp_test_util::CreateRule(
+      "rule #1", "Unknown", std::move(src_urls),
+      /*dst_urls=*/base::Value(base::Value::Type::LIST),
+      std::move(dst_components), std::move(restrictions)));
+
+  UpdatePolicyPref(std::move(rules));
+  histogram_tester_.ExpectBucketCount("Enterprise.Dlp.RestrictionConfigured",
+                                      DlpRulesManager::Restriction::kClipboard,
+                                      1);
+
+  std::string src_pattern;
+  std::string dst_pattern;
+  EXPECT_EQ(
+      DlpRulesManager::Level::kBlock,
+      dlp_rules_manager_.IsRestrictedComponent(
+          GURL(kExampleUrl), DlpRulesManager::Component::kUnknownComponent,
+          DlpRulesManager::Restriction::kClipboard, &src_pattern));
+  EXPECT_EQ(src_pattern, kExampleUrl);
+}
+
+TEST_F(DlpRulesManagerImplTest, UnknownLevel) {
+  base::Value rules(base::Value::Type::LIST);
+
+  base::Value src_urls(base::Value::Type::LIST);
+  src_urls.Append(kExampleUrl);
+
+  base::Value dst_urls(base::Value::Type::LIST);
+  dst_urls.Append(kWildCardMatching);
+
+  base::Value restrictions(base::Value::Type::LIST);
+  restrictions.Append(dlp_test_util::CreateRestrictionWithLevel(
+      dlp::kClipboardRestriction, "Wrong level"));
+
+  rules.Append(dlp_test_util::CreateRule(
+      "rule #1", "Unknown", std::move(src_urls), std::move(dst_urls),
+      /*dst_components=*/base::Value(base::Value::Type::LIST),
+      std::move(restrictions)));
+
+  UpdatePolicyPref(std::move(rules));
+  histogram_tester_.ExpectBucketCount("Enterprise.Dlp.RestrictionConfigured",
+                                      DlpRulesManager::Restriction::kClipboard,
+                                      0);
+}
+
 TEST_F(DlpRulesManagerImplTest, BlockPriority) {
   base::Value rules(base::Value::Type::LIST);
 
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
index 452382e..1d1a0df 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -258,7 +258,10 @@
 
 PasswordCheckDelegate::PasswordCheckDelegate(
     Profile* profile,
-    password_manager::SavedPasswordsPresenter* presenter)
+    password_manager::SavedPasswordsPresenter* presenter,
+    IdGenerator<password_manager::CredentialUIEntry,
+                int,
+                password_manager::CredentialUIEntry::Less>* id_generator)
     : profile_(profile),
       saved_passwords_presenter_(presenter),
       insecure_credentials_manager_(presenter,
@@ -271,7 +274,9 @@
       bulk_leak_check_service_adapter_(
           presenter,
           BulkLeakCheckServiceFactory::GetForProfile(profile_),
-          profile_->GetPrefs()) {
+          profile_->GetPrefs()),
+      id_generator_(id_generator) {
+  DCHECK(id_generator);
   observed_saved_passwords_presenter_.Observe(saved_passwords_presenter_.get());
   observed_insecure_credentials_manager_.Observe(
       &insecure_credentials_manager_);
@@ -287,17 +292,16 @@
 
 PasswordCheckDelegate::~PasswordCheckDelegate() = default;
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 PasswordCheckDelegate::GetCompromisedCredentials() {
   std::vector<CredentialUIEntry> ordered_credentials =
       insecure_credentials_manager_.GetInsecureCredentialEntries();
   OrderInsecureCredentials(ordered_credentials);
 
-  std::vector<api::passwords_private::InsecureCredential>
-      compromised_credentials;
+  std::vector<api::passwords_private::PasswordUiEntry> compromised_credentials;
   compromised_credentials.reserve(ordered_credentials.size());
   for (const auto& credential : ordered_credentials) {
-    api::passwords_private::InsecureCredential api_credential =
+    api::passwords_private::PasswordUiEntry api_credential =
         ConstructInsecureCredential(credential);
     api_credential.compromised_info =
         std::make_unique<api::passwords_private::CompromisedInfo>(
@@ -308,12 +312,12 @@
   return compromised_credentials;
 }
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 PasswordCheckDelegate::GetWeakCredentials() {
   std::vector<CredentialUIEntry> weak_credentials =
       insecure_credentials_manager_.GetWeakCredentialEntries();
 
-  std::vector<api::passwords_private::InsecureCredential> api_credentials;
+  std::vector<api::passwords_private::PasswordUiEntry> api_credentials;
   api_credentials.reserve(weak_credentials.size());
   for (auto& weak_credential : weak_credentials) {
     api_credentials.push_back(ConstructInsecureCredential(weak_credential));
@@ -322,52 +326,8 @@
   return api_credentials;
 }
 
-absl::optional<api::passwords_private::InsecureCredential>
-PasswordCheckDelegate::GetPlaintextInsecurePassword(
-    api::passwords_private::InsecureCredential credential) const {
-  const CredentialUIEntry* entry = FindMatchingEntry(credential);
-  if (!entry)
-    return absl::nullopt;
-
-  credential.password =
-      std::make_unique<std::string>(base::UTF16ToUTF8(entry->password));
-  return credential;
-}
-
-bool PasswordCheckDelegate::ChangeInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential,
-    base::StringPiece new_password) {
-  // Try to obtain the original CredentialUIEntry. Return false if fails.
-  const CredentialUIEntry* original_credential = FindMatchingEntry(credential);
-  if (!original_credential)
-    return false;
-
-  CredentialUIEntry updated_credential = *original_credential;
-  updated_credential.password = base::UTF8ToUTF16(new_password);
-  switch (saved_passwords_presenter_->EditSavedCredentials(
-      *original_credential, updated_credential)) {
-    case password_manager::SavedPasswordsPresenter::EditResult::kSuccess:
-    case password_manager::SavedPasswordsPresenter::EditResult::kNothingChanged:
-      return true;
-    case password_manager::SavedPasswordsPresenter::EditResult::kNotFound:
-    case password_manager::SavedPasswordsPresenter::EditResult::kAlreadyExisits:
-    case password_manager::SavedPasswordsPresenter::EditResult::kEmptyPassword:
-      return false;
-  }
-}
-
-bool PasswordCheckDelegate::RemoveInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
-  // Try to obtain the original CredentialUIEntry. Return false if fails.
-  const CredentialUIEntry* entry = FindMatchingEntry(credential);
-  if (!entry)
-    return false;
-
-  return saved_passwords_presenter_->RemoveCredential(*entry);
-}
-
 bool PasswordCheckDelegate::MuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   // Try to obtain the original CredentialUIEntry. Return false if fails.
   const CredentialUIEntry* entry = FindMatchingEntry(credential);
   if (!entry)
@@ -377,7 +337,7 @@
 }
 
 bool PasswordCheckDelegate::UnmuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   // Try to obtain the original CredentialUIEntry. Return false if fails.
   const CredentialUIEntry* entry = FindMatchingEntry(credential);
   if (!entry)
@@ -389,7 +349,7 @@
 // Records that a change password flow was started for |credential| and
 // whether |is_manual_flow| applies to the flow.
 void PasswordCheckDelegate::RecordChangePasswordFlowStarted(
-    const api::passwords_private::InsecureCredential& credential,
+    const api::passwords_private::PasswordUiEntry& credential,
     bool is_manual_flow) {
   // If the |credential| does not have a |change_password_url|, skip it.
   if (!credential.change_password_url)
@@ -458,11 +418,11 @@
   if (PasswordsPrivateEventRouter* event_router =
           PasswordsPrivateEventRouterFactory::GetForProfile(profile_)) {
     // Only update if at least one credential now has a startable script.
-    std::vector<api::passwords_private::InsecureCredential> credentials =
+    std::vector<api::passwords_private::PasswordUiEntry> credentials =
         GetCompromisedCredentials();
-    if (base::ranges::any_of(credentials,
-                             &api::passwords_private::InsecureCredential::
-                                 has_startable_script)) {
+    if (base::ranges::any_of(
+            credentials,
+            &api::passwords_private::PasswordUiEntry::has_startable_script)) {
       UMA_HISTOGRAM_ENUMERATION(
           kPasswordCheckScriptsCacheStateUmaKey,
           PasswordCheckScriptsCacheState::kCacheStaleAndUiUpdate);
@@ -620,9 +580,8 @@
 }
 
 const CredentialUIEntry* PasswordCheckDelegate::FindMatchingEntry(
-    const api::passwords_private::InsecureCredential& credential) const {
-  const CredentialUIEntry* entry =
-      insecure_credential_id_generator_.TryGetKey(credential.id);
+    const api::passwords_private::PasswordUiEntry& credential) const {
+  const CredentialUIEntry* entry = id_generator_->TryGetKey(credential.id);
   if (!entry)
     return nullptr;
 
@@ -669,16 +628,17 @@
   }
 }
 
-api::passwords_private::InsecureCredential
+api::passwords_private::PasswordUiEntry
 PasswordCheckDelegate::ConstructInsecureCredential(
     const CredentialUIEntry& entry) {
-  api::passwords_private::InsecureCredential api_credential;
+  api::passwords_private::PasswordUiEntry api_credential;
   auto facet = password_manager::FacetURI::FromPotentiallyInvalidSpec(
       entry.signon_realm);
   api_credential.is_android_credential = facet.IsValidAndroidFacetURI();
-  api_credential.id = insecure_credential_id_generator_.GenerateId(entry);
+  api_credential.id = id_generator_->GenerateId(entry);
   api_credential.username = base::UTF16ToUTF8(entry.username);
   api_credential.urls = CreateUrlCollectionFromCredential(entry);
+  api_credential.stored_in = StoreSetFromCredential(entry);
   if (api_credential.is_android_credential) {
     // |change_password_url| need special handling for Android. Here we use
     // affiliation information instead of the origin.
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
index 649fad5..cfce262 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -49,8 +49,12 @@
   using RefreshScriptsIfNecessaryCallback =
       PasswordsPrivateDelegate::RefreshScriptsIfNecessaryCallback;
 
-  PasswordCheckDelegate(Profile* profile,
-                        password_manager::SavedPasswordsPresenter* presenter);
+  PasswordCheckDelegate(
+      Profile* profile,
+      password_manager::SavedPasswordsPresenter* presenter,
+      IdGenerator<password_manager::CredentialUIEntry,
+                  int,
+                  password_manager::CredentialUIEntry::Less>* id_generator);
   PasswordCheckDelegate(const PasswordCheckDelegate&) = delete;
   PasswordCheckDelegate& operator=(const PasswordCheckDelegate&) = delete;
   ~PasswordCheckDelegate() override;
@@ -58,44 +62,26 @@
   // Obtains information about compromised credentials. This includes the last
   // time a check was run, as well as all compromised credentials that are
   // present in the password store.
-  std::vector<api::passwords_private::InsecureCredential>
+  std::vector<api::passwords_private::PasswordUiEntry>
   GetCompromisedCredentials();
 
   // Obtains information about weak credentials.
-  std::vector<api::passwords_private::InsecureCredential> GetWeakCredentials();
-
-  // Requests the plaintext password for `credential`. If successful, this
-  // returns `credential` with its `password` member set. This can fail if no
-  // matching insecure credential can be found in the password store.
-  absl::optional<api::passwords_private::InsecureCredential>
-  GetPlaintextInsecurePassword(
-      api::passwords_private::InsecureCredential credential) const;
-
-  // Attempts to change the stored password of `credential` to `new_password`.
-  // Returns whether the change succeeded.
-  bool ChangeInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential,
-      base::StringPiece new_password);
-
-  // Attempts to remove `credential` from the password store. Returns whether
-  // the remove succeeded.
-  bool RemoveInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential);
+  std::vector<api::passwords_private::PasswordUiEntry> GetWeakCredentials();
 
   // Attempts to mute `credential` from the password store. Returns whether
   // the mute succeeded.
   bool MuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential);
+      const api::passwords_private::PasswordUiEntry& credential);
 
   // Attempts to unmute `credential` from the password store. Returns whether
   // the unmute succeeded.
   bool UnmuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential);
+      const api::passwords_private::PasswordUiEntry& credential);
 
   // Records that a change password flow was started for `credential` and
   // whether `is_manual_flow` applies to the flow.
   void RecordChangePasswordFlowStarted(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       bool is_manual_flow);
 
   // Refreshes the cache for automatic password change scripts if that is stale
@@ -144,13 +130,12 @@
                         password_manager::IsLeaked is_leaked) override;
 
   // Tries to find the matching CredentialUIEntry for |credential|. It
-  // performs a look-up in |insecure_credential_id_generator_| using
-  // |credential.id|. If a matching value exists it also verifies that signon
-  // realm, username and when possible password match.
-  // Returns a pointer to the matching CredentialUIEntry on success or
-  // nullptr otherwise.
+  // performs a look-up in |id_generator_| using |credential.id|. If a matching
+  // value exists it also verifies that signon realm, username and when possible
+  // password match. Returns a pointer to the matching CredentialUIEntry on
+  // success or nullptr otherwise.
   const password_manager::CredentialUIEntry* FindMatchingEntry(
-      const api::passwords_private::InsecureCredential& credential) const;
+      const api::passwords_private::PasswordUiEntry& credential) const;
 
   // Reacts to a refreshed password scripts cache. Checks whether any of the
   // compromised credentials have a password script and only then calls the
@@ -174,8 +159,8 @@
   // `OnStateChanged`.
   void NotifyPasswordCheckStatusChanged();
 
-  // Constructs `InsecureCredential` from `CredentialUIEntry`.
-  api::passwords_private::InsecureCredential ConstructInsecureCredential(
+  // Constructs `PasswordUiEntry` from `CredentialUIEntry`.
+  api::passwords_private::PasswordUiEntry ConstructInsecureCredential(
       const password_manager::CredentialUIEntry& entry);
 
   // Returns a raw pointer to the `PasswordChangeSuccessTracker` associated
@@ -242,12 +227,12 @@
       observed_bulk_leak_check_service_{this};
 
   // An id generator for insecure credentials. Required to match
-  // `api::passwords_private::InsecureCredential` instances passed to the UI
+  // `api::passwords_private::PasswordUiEntry` instances passed to the UI
   // with the underlying `CredentialUIEntry` they are based on.
-  IdGenerator<password_manager::CredentialUIEntry,
-              int,
-              password_manager::CredentialUIEntry::Less>
-      insecure_credential_id_generator_;
+  raw_ptr<IdGenerator<password_manager::CredentialUIEntry,
+                      int,
+                      password_manager::CredentialUIEntry::Less>>
+      id_generator_;
 
   base::WeakPtrFactory<PasswordCheckDelegate> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
index a8592dcc..925b23a 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
@@ -85,8 +85,8 @@
 constexpr char16_t kWeakPassword2[] = u"111111";
 
 using api::passwords_private::CompromisedInfo;
-using api::passwords_private::InsecureCredential;
 using api::passwords_private::PasswordCheckStatus;
+using api::passwords_private::PasswordUiEntry;
 using api::passwords_private::UrlCollection;
 using password_manager::BulkLeakCheckDelegateInterface;
 using password_manager::BulkLeakCheckService;
@@ -258,13 +258,12 @@
     const std::u16string& username) {
   auto change_password_url_field_matcher =
       change_password_url.has_value()
-          ? Field(&InsecureCredential::change_password_url,
+          ? Field(&PasswordUiEntry::change_password_url,
                   Pointee(change_password_url.value()))
-          : Field(&InsecureCredential::change_password_url, IsNull());
-  return AllOf(
-      Field(&InsecureCredential::username, base::UTF16ToASCII(username)),
-      Field(&InsecureCredential::urls,
-            ExpectUrls(formatted_origin, detailed_origin)));
+          : Field(&PasswordUiEntry::change_password_url, IsNull());
+  return AllOf(Field(&PasswordUiEntry::username, base::UTF16ToASCII(username)),
+               Field(&PasswordUiEntry::urls,
+                     ExpectUrls(formatted_origin, detailed_origin)));
 }
 
 // Creates matcher for a given compromised credential
@@ -278,18 +277,17 @@
     api::passwords_private::CompromiseType compromise_type) {
   auto change_password_url_field_matcher =
       change_password_url.has_value()
-          ? Field(&InsecureCredential::change_password_url,
+          ? Field(&PasswordUiEntry::change_password_url,
                   Pointee(change_password_url.value()))
-          : Field(&InsecureCredential::change_password_url, IsNull());
-  return AllOf(
-      Field(&InsecureCredential::username, base::UTF16ToASCII(username)),
-      change_password_url_field_matcher,
-      Field(&InsecureCredential::urls,
-            ExpectUrls(formatted_origin, detailed_origin)),
-      Field(&InsecureCredential::compromised_info,
-            Pointee(ExpectCompromisedInfo(elapsed_time_since_compromise,
-                                          elapsed_time_since_compromise_str,
-                                          compromise_type))));
+          : Field(&PasswordUiEntry::change_password_url, IsNull());
+  return AllOf(Field(&PasswordUiEntry::username, base::UTF16ToASCII(username)),
+               change_password_url_field_matcher,
+               Field(&PasswordUiEntry::urls,
+                     ExpectUrls(formatted_origin, detailed_origin)),
+               Field(&PasswordUiEntry::compromised_info,
+                     Pointee(ExpectCompromisedInfo(
+                         elapsed_time_since_compromise,
+                         elapsed_time_since_compromise_str, compromise_type))));
 }
 
 // Creates a simplified matcher that only checks the username name and
@@ -297,8 +295,8 @@
 auto ExpectCredentialWithScriptInfo(const std::u16string& username,
                                     bool has_startable_script) {
   return AllOf(
-      Field(&InsecureCredential::username, base::UTF16ToASCII(username)),
-      Field(&InsecureCredential::has_startable_script, has_startable_script));
+      Field(&PasswordUiEntry::username, base::UTF16ToASCII(username)),
+      Field(&PasswordUiEntry::has_startable_script, has_startable_script));
 }
 
 class PasswordCheckDelegateTest : public ::testing::Test {
@@ -327,6 +325,11 @@
   SavedPasswordsPresenter& presenter() { return presenter_; }
   PasswordCheckDelegate& delegate() { return delegate_; }
 
+  PasswordCheckDelegate CreateDelegate(SavedPasswordsPresenter* presenter) {
+    return PasswordCheckDelegate(&profile_, presenter,
+                                 &credential_id_generator_);
+  }
+
  private:
   content::BrowserTaskEnvironment task_env_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@@ -347,8 +350,13 @@
       CreateAndUsePasswordScriptsFetcher(&profile_);
   raw_ptr<syncer::TestSyncService> sync_service_ =
       CreateAndUseSyncService(&profile_);
+  IdGenerator<password_manager::CredentialUIEntry,
+              int,
+              password_manager::CredentialUIEntry::Less>
+      credential_id_generator_;
   SavedPasswordsPresenter presenter_{store_};
-  PasswordCheckDelegate delegate_{&profile_, &presenter_};
+  PasswordCheckDelegate delegate_{&profile_, &presenter_,
+                                  &credential_id_generator_};
 };
 
 }  // namespace
@@ -637,214 +645,6 @@
             event_router_observer().events().at(kEventName)->histogram_value);
 }
 
-TEST_F(PasswordCheckDelegateTest, GetPlaintextInsecurePasswordRejectsWrongId) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(0, credential.id);
-
-  // Purposefully set a wrong id and verify that trying to get a plaintext
-  // password fails.
-  credential.id = 1;
-  EXPECT_EQ(absl::nullopt,
-            delegate().GetPlaintextInsecurePassword(std::move(credential)));
-}
-
-TEST_F(PasswordCheckDelegateTest,
-       GetPlaintextInsecurePasswordRejectsWrongSignonRealm) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-
-  RunUntilIdle();
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(kExampleCom, credential.urls.signon_realm);
-
-  // Purposefully set a wrong signon realm and verify that trying to get a
-  // plaintext password fails.
-  credential.urls.signon_realm = kExampleOrg;
-  EXPECT_EQ(absl::nullopt,
-            delegate().GetPlaintextInsecurePassword(std::move(credential)));
-}
-
-TEST_F(PasswordCheckDelegateTest,
-       GetPlaintextInsecurePasswordRejectsWrongUsername) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
-
-  // Purposefully set a wrong username and verify that trying to get a
-  // plaintext password fails.
-  credential.urls.signon_realm = base::UTF16ToASCII(kUsername2);
-  EXPECT_EQ(absl::nullopt,
-            delegate().GetPlaintextInsecurePassword(std::move(credential)));
-}
-
-TEST_F(PasswordCheckDelegateTest,
-       GetPlaintextInsecurePasswordReturnsCorrectPassword) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(0, credential.id);
-  EXPECT_EQ(kExampleCom, credential.urls.signon_realm);
-  EXPECT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
-  EXPECT_EQ(nullptr, credential.password);
-
-  absl::optional<InsecureCredential> opt_credential =
-      delegate().GetPlaintextInsecurePassword(std::move(credential));
-  ASSERT_TRUE(opt_credential.has_value());
-  EXPECT_EQ(0, opt_credential->id);
-  EXPECT_EQ(kExampleCom, opt_credential->urls.signon_realm);
-  EXPECT_EQ(base::UTF16ToASCII(kUsername1), opt_credential->username);
-  EXPECT_EQ(base::UTF16ToASCII(kPassword1), *opt_credential->password);
-}
-
-// Test that changing a insecure password fails if the ids don't match.
-TEST_F(PasswordCheckDelegateTest, ChangeInsecureCredentialIdMismatch) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(0, credential.id);
-  credential.id = 1;
-
-  EXPECT_FALSE(delegate().ChangeInsecureCredential(credential, "new_pass"));
-}
-
-// Test that changing a insecure password fails if the underlying insecure
-// credential no longer exists.
-TEST_F(PasswordCheckDelegateTest, ChangeInsecureCredentialStaleData) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-
-  store().RemoveLogin(form);
-  RunUntilIdle();
-
-  EXPECT_FALSE(delegate().ChangeInsecureCredential(credential, "new_pass"));
-}
-
-// Test that changing a insecure password succeeds.
-TEST_F(PasswordCheckDelegateTest, ChangeInsecureCredentialSuccess) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(0, credential.id);
-  EXPECT_EQ(kExampleCom, credential.urls.signon_realm);
-  EXPECT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
-  EXPECT_EQ(kPassword1,
-            store().stored_passwords().at(kExampleCom).at(0).password_value);
-
-  EXPECT_TRUE(delegate().ChangeInsecureCredential(
-      credential, base::UTF16ToASCII(kPassword2)));
-  RunUntilIdle();
-
-  EXPECT_EQ(kPassword2,
-            store().stored_passwords().at(kExampleCom).at(0).password_value);
-}
-
-// Test that changing a insecure password removes duplicates from store.
-// https://crbug.com/1334160
-TEST_F(PasswordCheckDelegateTest,
-       DISABLED_ChangeInsecureCredentialRemovesDupes) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1, kPassword1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-
-  PasswordForm duplicate_form = MakeSavedPassword(
-      kExampleCom, kUsername1, kPassword1, u"different_element");
-  AddIssueToForm(&duplicate_form, InsecureType::kLeaked);
-  store().AddLogin(duplicate_form);
-
-  RunUntilIdle();
-
-  EXPECT_EQ(2u, store().stored_passwords().at(kExampleCom).size());
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_TRUE(delegate().ChangeInsecureCredential(
-      credential, base::UTF16ToASCII(kPassword2)));
-  RunUntilIdle();
-
-  EXPECT_EQ(1u, store().stored_passwords().at(kExampleCom).size());
-  EXPECT_EQ(kPassword2,
-            store().stored_passwords().at(kExampleCom).at(0).password_value);
-}
-
-// Test that removing a insecure password fails if the ids don't match.
-TEST_F(PasswordCheckDelegateTest, RemoveInsecureCredentialIdMismatch) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_EQ(0, credential.id);
-  credential.id = 1;
-
-  EXPECT_FALSE(delegate().RemoveInsecureCredential(credential));
-}
-
-// Test that removing a insecure password fails if the underlying insecure
-// credential no longer exists.
-TEST_F(PasswordCheckDelegateTest, RemoveInsecureCredentialStaleData) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  store().RemoveLogin(form);
-  RunUntilIdle();
-
-  EXPECT_FALSE(delegate().RemoveInsecureCredential(credential));
-}
-
-// Test that removing a insecure password succeeds.
-TEST_F(PasswordCheckDelegateTest, RemoveInsecureCredentialSuccess) {
-  PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
-  AddIssueToForm(&form, InsecureType::kLeaked);
-  store().AddLogin(form);
-  RunUntilIdle();
-
-  InsecureCredential credential =
-      std::move(delegate().GetCompromisedCredentials().at(0));
-  EXPECT_TRUE(delegate().RemoveInsecureCredential(credential));
-  RunUntilIdle();
-  EXPECT_TRUE(store().IsEmpty());
-
-  // Expect another removal of the same credential to fail.
-  EXPECT_FALSE(delegate().RemoveInsecureCredential(credential));
-}
-
 // Test that muting a insecure password succeeds.
 TEST_F(PasswordCheckDelegateTest, MuteInsecureCredentialSuccess) {
   PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1);
@@ -852,7 +652,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   EXPECT_TRUE(delegate().MuteInsecureCredential(credential));
   RunUntilIdle();
@@ -875,7 +675,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   store().RemoveLogin(form);
   RunUntilIdle();
@@ -890,7 +690,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   EXPECT_EQ(0, credential.id);
   credential.id = 1;
@@ -905,7 +705,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   EXPECT_TRUE(delegate().UnmuteInsecureCredential(credential));
   RunUntilIdle();
@@ -928,7 +728,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   store().RemoveLogin(form);
   RunUntilIdle();
@@ -943,7 +743,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   EXPECT_EQ(0, credential.id);
   credential.id = 1;
@@ -958,7 +758,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
 
@@ -979,7 +779,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
 
@@ -1015,7 +815,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   ASSERT_EQ(base::UTF16ToASCII(kUsername2), credential.username);
 
@@ -1038,7 +838,7 @@
   store().AddLogin(form);
   RunUntilIdle();
 
-  InsecureCredential credential =
+  PasswordUiEntry credential =
       std::move(delegate().GetCompromisedCredentials().at(0));
   ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username);
 
@@ -1407,7 +1207,7 @@
   // Use a local delegate instead of |delegate()| so that the Password Store can
   // be set-up prior to constructing the object.
   SavedPasswordsPresenter new_presenter(&store());
-  PasswordCheckDelegate delegate(&profile(), &new_presenter);
+  PasswordCheckDelegate delegate = CreateDelegate(&new_presenter);
   new_presenter.Init();
   delegate.StartPasswordCheck(callback1.Get());
   delegate.StartPasswordCheck(callback2.Get());
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
index ec5d92f..9f7d8aa 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
@@ -265,87 +265,6 @@
           GetDelegate(browser_context())->GetWeakCredentials())));
 }
 
-// PasswordsPrivateGetPlaintextInsecurePasswordFunction:
-PasswordsPrivateGetPlaintextInsecurePasswordFunction::
-    ~PasswordsPrivateGetPlaintextInsecurePasswordFunction() = default;
-
-ResponseAction PasswordsPrivateGetPlaintextInsecurePasswordFunction::Run() {
-  auto parameters =
-      api::passwords_private::GetPlaintextInsecurePassword::Params::Create(
-          args());
-  EXTENSION_FUNCTION_VALIDATE(parameters);
-
-  GetDelegate(browser_context())
-      ->GetPlaintextInsecurePassword(
-          std::move(parameters->credential), parameters->reason,
-          GetSenderWebContents(),
-          base::BindOnce(&PasswordsPrivateGetPlaintextInsecurePasswordFunction::
-                             GotCredential,
-                         this));
-
-  // GotCredential() might respond before we reach this point.
-  return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void PasswordsPrivateGetPlaintextInsecurePasswordFunction::GotCredential(
-    absl::optional<api::passwords_private::InsecureCredential> credential) {
-  if (!credential) {
-    Respond(
-        Error("Could not obtain plaintext insecure password. Either the user "
-              "is not authenticated or no matching password could be found."));
-    return;
-  }
-
-  Respond(ArgumentList(
-      api::passwords_private::GetPlaintextInsecurePassword::Results::Create(
-          *credential)));
-}
-
-// PasswordsPrivateChangeInsecureCredentialFunction:
-PasswordsPrivateChangeInsecureCredentialFunction::
-    ~PasswordsPrivateChangeInsecureCredentialFunction() = default;
-
-ResponseAction PasswordsPrivateChangeInsecureCredentialFunction::Run() {
-  auto parameters =
-      api::passwords_private::ChangeInsecureCredential::Params::Create(args());
-  EXTENSION_FUNCTION_VALIDATE(parameters);
-
-  if (parameters->new_password.empty()) {
-    return RespondNow(
-        Error("Could not change the insecure credential. The new password "
-              "can't be empty."));
-  }
-
-  if (!GetDelegate(browser_context())
-           ->ChangeInsecureCredential(parameters->credential,
-                                      parameters->new_password)) {
-    return RespondNow(Error(
-        "Could not change the insecure credential. Either the user is not "
-        "authenticated or no matching password could be found."));
-  }
-
-  return RespondNow(NoArguments());
-}
-
-// PasswordsPrivateRemoveInsecureCredentialFunction:
-PasswordsPrivateRemoveInsecureCredentialFunction::
-    ~PasswordsPrivateRemoveInsecureCredentialFunction() = default;
-
-ResponseAction PasswordsPrivateRemoveInsecureCredentialFunction::Run() {
-  auto parameters =
-      api::passwords_private::RemoveInsecureCredential::Params::Create(args());
-  EXTENSION_FUNCTION_VALIDATE(parameters);
-
-  if (!GetDelegate(browser_context())
-           ->RemoveInsecureCredential(parameters->credential)) {
-    return RespondNow(
-        Error("Could not remove the insecure credential. Probably no matching "
-              "password could be found."));
-  }
-
-  return RespondNow(NoArguments());
-}
-
 // PasswordsPrivateMuteInsecureCredentialFunction:
 PasswordsPrivateMuteInsecureCredentialFunction::
     ~PasswordsPrivateMuteInsecureCredentialFunction() = default;
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
index c0243cb..64e668cf 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
@@ -246,49 +246,6 @@
   ResponseAction Run() override;
 };
 
-class PasswordsPrivateGetPlaintextInsecurePasswordFunction
-    : public ExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getPlaintextInsecurePassword",
-                             PASSWORDSPRIVATE_GETPLAINTEXTINSECUREPASSWORD)
-
- protected:
-  ~PasswordsPrivateGetPlaintextInsecurePasswordFunction() override;
-
-  // ExtensionFunction overrides.
-  ResponseAction Run() override;
-
- private:
-  void GotCredential(
-      absl::optional<api::passwords_private::InsecureCredential> credential);
-};
-
-class PasswordsPrivateChangeInsecureCredentialFunction
-    : public ExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("passwordsPrivate.changeInsecureCredential",
-                             PASSWORDSPRIVATE_CHANGEINSECURECREDENTIAL)
-
- protected:
-  ~PasswordsPrivateChangeInsecureCredentialFunction() override;
-
-  // ExtensionFunction overrides.
-  ResponseAction Run() override;
-};
-
-class PasswordsPrivateRemoveInsecureCredentialFunction
-    : public ExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removeInsecureCredential",
-                             PASSWORDSPRIVATE_REMOVEINSECURECREDENTIAL)
-
- protected:
-  ~PasswordsPrivateRemoveInsecureCredentialFunction() override;
-
-  // ExtensionFunction overrides.
-  ResponseAction Run() override;
-};
-
 class PasswordsPrivateMuteInsecureCredentialFunction
     : public ExtensionFunction {
  public:
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
index 05906d4..cece829 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
@@ -247,35 +247,6 @@
   EXPECT_TRUE(RunPasswordsSubtest("getWeakCredentials")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, GetPlaintextInsecurePassword) {
-  EXPECT_TRUE(RunPasswordsSubtest("getPlaintextInsecurePassword")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
-                       GetPlaintextInsecurePasswordFails) {
-  ResetPlaintextPassword();
-  EXPECT_TRUE(RunPasswordsSubtest("getPlaintextInsecurePasswordFails"))
-      << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
-                       ChangeInsecureCredentialWithEmptyPasswordFails) {
-  EXPECT_TRUE(
-      RunPasswordsSubtest("changeInsecureCredentialWithEmptyPasswordFails"))
-      << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, ChangeInsecureCredentialFails) {
-  EXPECT_TRUE(RunPasswordsSubtest("changeInsecureCredentialFails")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
-                       ChangeInsecureCredentialSucceeds) {
-  AddCompromisedCredential(0);
-  EXPECT_TRUE(RunPasswordsSubtest("changeInsecureCredentialSucceeds"))
-      << message_;
-}
-
 IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, OptInForAccountStorage) {
   SetOptedInForAccountStorage(false);
   EXPECT_TRUE(RunPasswordsSubtest("optInForAccountStorage")) << message_;
@@ -286,24 +257,6 @@
   EXPECT_TRUE(RunPasswordsSubtest("optOutForAccountStorage")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RemoveInsecureCredentialFails) {
-  EXPECT_TRUE(RunPasswordsSubtest("removeInsecureCredentialFails")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
-                       RemoveInsecureCredentialSucceeds) {
-  AddCompromisedCredential(0);
-  EXPECT_TRUE(RunPasswordsSubtest("removeInsecureCredentialSucceeds"))
-      << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
-                       MuteInsecureCredentialSucceeds) {
-  AddCompromisedCredential(0);
-  EXPECT_TRUE(RunPasswordsSubtest("muteInsecureCredentialSucceeds"))
-      << message_;
-}
-
 IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, MuteInsecureCredentialFails) {
   EXPECT_TRUE(RunPasswordsSubtest("muteInsecureCredentialFails")) << message_;
 }
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
index 4f7ac06f..3079618e 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
@@ -39,9 +39,6 @@
   using StartPasswordCheckCallback =
       base::OnceCallback<void(password_manager::BulkLeakCheckService::State)>;
 
-  using PlaintextInsecurePasswordCallback = base::OnceCallback<void(
-      absl::optional<api::passwords_private::InsecureCredential>)>;
-
   using StartAutomatedPasswordChangeCallback = base::OnceCallback<void(bool)>;
 
   ~PasswordsPrivateDelegate() override = default;
@@ -161,47 +158,27 @@
   // Obtains information about compromised credentials. This includes the last
   // time a check was run, as well as all compromised credentials that are
   // present in the password store.
-  virtual std::vector<api::passwords_private::InsecureCredential>
+  virtual std::vector<api::passwords_private::PasswordUiEntry>
   GetCompromisedCredentials() = 0;
 
   // Obtains information about weak credentials.
-  virtual std::vector<api::passwords_private::InsecureCredential>
+  virtual std::vector<api::passwords_private::PasswordUiEntry>
   GetWeakCredentials() = 0;
 
-  // Requests the plaintext password for |credential| due to |reason|. If
-  // successful, |callback| gets invoked with the same |credential|, whose
-  // |password| field will be set.
-  virtual void GetPlaintextInsecurePassword(
-      api::passwords_private::InsecureCredential credential,
-      api::passwords_private::PlaintextReason reason,
-      content::WebContents* web_contents,
-      PlaintextInsecurePasswordCallback callback) = 0;
-
-  // Attempts to change the stored password of |credential| to |new_password|.
-  // Returns whether the change succeeded.
-  virtual bool ChangeInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential,
-      base::StringPiece new_password) = 0;
-
-  // Attempts to remove |credential| from the password store. Returns whether
-  // the remove succeeded.
-  virtual bool RemoveInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) = 0;
-
   // Attempts to mute |credential| from the password store. Returns whether
   // the mute succeeded.
   virtual bool MuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) = 0;
+      const api::passwords_private::PasswordUiEntry& credential) = 0;
 
   // Attempts to unmute |credential| from the password store. Returns whether
   // the unmute succeeded.
   virtual bool UnmuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) = 0;
+      const api::passwords_private::PasswordUiEntry& credential) = 0;
 
   // Records that a change password flow was started for |credential| and
   // whether |is_manual_flow| applies to the flow.
   virtual void RecordChangePasswordFlowStarted(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       bool is_manual_flow) = 0;
 
   // Refreshes the cache for automatic password change scripts if that is stale
@@ -223,7 +200,7 @@
   // whether the credential was changed successfully by calling `callback` with
   // a boolean parameter.
   virtual void StartAutomatedPasswordChange(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       StartAutomatedPasswordChangeCallback callback) = 0;
 
   // Returns a pointer to the current instance of InsecureCredentialsManager.
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
index 0860c41..40f3219b 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -149,23 +149,6 @@
   return {};
 }
 
-extensions::api::passwords_private::PasswordStoreSet ConvertToAPIStore(
-    const base::flat_set<password_manager::PasswordForm::Store>& stores) {
-  if (stores.contains(password_manager::PasswordForm::Store::kAccountStore) &&
-      stores.contains(password_manager::PasswordForm::Store::kProfileStore)) {
-    return extensions::api::passwords_private::
-        PASSWORD_STORE_SET_DEVICE_AND_ACCOUNT;
-  }
-  if (stores.contains(password_manager::PasswordForm::Store::kAccountStore)) {
-    return extensions::api::passwords_private::PASSWORD_STORE_SET_ACCOUNT;
-  }
-  if (stores.contains(password_manager::PasswordForm::Store::kProfileStore)) {
-    return extensions::api::passwords_private::PASSWORD_STORE_SET_DEVICE;
-  }
-  NOTREACHED();
-  return extensions::api::passwords_private::PASSWORD_STORE_SET_DEVICE;
-}
-
 }  // namespace
 
 namespace extensions {
@@ -195,7 +178,9 @@
               base::BindRepeating(&PasswordsPrivateDelegateImpl::
                                       OnAccountStorageOptInStateChanged,
                                   base::Unretained(this)))),
-      password_check_delegate_(profile, &saved_passwords_presenter_),
+      password_check_delegate_(profile,
+                               &saved_passwords_presenter_,
+                               &credential_id_generator_),
       current_entries_initialized_(false),
       is_initialized_(false),
       web_contents_(nullptr) {
@@ -417,7 +402,7 @@
       entry.username = base::UTF16ToUTF8(credential.username);
       entry.note = base::UTF16ToUTF8(credential.note.value);
       entry.id = id;
-      entry.stored_in = ConvertToAPIStore(credential.stored_in);
+      entry.stored_in = StoreSetFromCredential(credential);
       entry.is_android_credential =
           password_manager::IsValidAndroidFacetURI(credential.signon_realm);
       if (!credential.federation_origin.opaque()) {
@@ -547,56 +532,28 @@
       signin_metrics::ReauthAccessPoint::kPasswordSettings, base::DoNothing());
 }
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 PasswordsPrivateDelegateImpl::GetCompromisedCredentials() {
   return password_check_delegate_.GetCompromisedCredentials();
 }
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 PasswordsPrivateDelegateImpl::GetWeakCredentials() {
   return password_check_delegate_.GetWeakCredentials();
 }
 
-void PasswordsPrivateDelegateImpl::GetPlaintextInsecurePassword(
-    api::passwords_private::InsecureCredential credential,
-    api::passwords_private::PlaintextReason reason,
-    content::WebContents* web_contents,
-    PlaintextInsecurePasswordCallback callback) {
-  // TODO(crbug.com/495290): Pass the native window directly to the
-  // reauth-handling code.
-  web_contents_ = web_contents;
-  password_access_authenticator_.EnsureUserIsAuthenticated(
-      GetReauthPurpose(reason),
-      base::BindOnce(&PasswordsPrivateDelegateImpl::
-                         OnGetPlaintextInsecurePasswordAuthResult,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(credential),
-                     reason, std::move(callback)));
-}
-
-bool PasswordsPrivateDelegateImpl::ChangeInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential,
-    base::StringPiece new_password) {
-  return password_check_delegate_.ChangeInsecureCredential(credential,
-                                                           new_password);
-}
-
-bool PasswordsPrivateDelegateImpl::RemoveInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
-  return password_check_delegate_.RemoveInsecureCredential(credential);
-}
-
 bool PasswordsPrivateDelegateImpl::MuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   return password_check_delegate_.MuteInsecureCredential(credential);
 }
 
 bool PasswordsPrivateDelegateImpl::UnmuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   return password_check_delegate_.UnmuteInsecureCredential(credential);
 }
 
 void PasswordsPrivateDelegateImpl::RecordChangePasswordFlowStarted(
-    const api::passwords_private::InsecureCredential& credential,
+    const api::passwords_private::PasswordUiEntry& credential,
     bool is_manual_flow) {
   password_check_delegate_.RecordChangePasswordFlowStarted(credential,
                                                            is_manual_flow);
@@ -622,7 +579,7 @@
 }
 
 void PasswordsPrivateDelegateImpl::StartAutomatedPasswordChange(
-    const api::passwords_private::InsecureCredential& credential,
+    const api::passwords_private::PasswordUiEntry& credential,
     StartAutomatedPasswordChangeCallback callback) {
   if (!credential.change_password_url) {
     std::move(callback).Run(false);
@@ -727,20 +684,6 @@
       .Run(accepted ? std::string() : kExportInProgress);
 }
 
-void PasswordsPrivateDelegateImpl::OnGetPlaintextInsecurePasswordAuthResult(
-    api::passwords_private::InsecureCredential credential,
-    api::passwords_private::PlaintextReason reason,
-    PlaintextInsecurePasswordCallback callback,
-    bool authenticated) {
-  if (!authenticated) {
-    std::move(callback).Run(absl::nullopt);
-    return;
-  }
-
-  std::move(callback).Run(password_check_delegate_.GetPlaintextInsecurePassword(
-      std::move(credential)));
-}
-
 void PasswordsPrivateDelegateImpl::OnAccountStorageOptInStateChanged() {
   PasswordsPrivateEventRouter* router =
       PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
index e6f3eb7c..fe616f8 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
@@ -88,26 +88,16 @@
   // TODO(crbug.com/1102294): Mimic the signature in PasswordFeatureManager.
   void SetAccountStorageOptIn(bool opt_in,
                               content::WebContents* web_contents) override;
-  std::vector<api::passwords_private::InsecureCredential>
+  std::vector<api::passwords_private::PasswordUiEntry>
   GetCompromisedCredentials() override;
-  std::vector<api::passwords_private::InsecureCredential> GetWeakCredentials()
+  std::vector<api::passwords_private::PasswordUiEntry> GetWeakCredentials()
       override;
-  void GetPlaintextInsecurePassword(
-      api::passwords_private::InsecureCredential credential,
-      api::passwords_private::PlaintextReason reason,
-      content::WebContents* web_contents,
-      PlaintextInsecurePasswordCallback callback) override;
-  bool ChangeInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential,
-      base::StringPiece new_password) override;
-  bool RemoveInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
   bool MuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
+      const api::passwords_private::PasswordUiEntry& credential) override;
   bool UnmuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
+      const api::passwords_private::PasswordUiEntry& credential) override;
   void RecordChangePasswordFlowStarted(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       bool is_manual_flow) override;
   void RefreshScriptsIfNecessary(
       RefreshScriptsIfNecessaryCallback callback) override;
@@ -115,7 +105,7 @@
   void StopPasswordCheck() override;
   api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override;
   void StartAutomatedPasswordChange(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       StartAutomatedPasswordChangeCallback callback) override;
   password_manager::InsecureCredentialsManager* GetInsecureCredentialsManager()
       override;
@@ -178,13 +168,6 @@
       content::WebContents* web_contents,
       bool authenticated);
 
-  // Callback for GetPlaintextInsecurePassword() after authentication check.
-  void OnGetPlaintextInsecurePasswordAuthResult(
-      api::passwords_private::InsecureCredential credential,
-      api::passwords_private::PlaintextReason reason,
-      PlaintextInsecurePasswordCallback callback,
-      bool authenticated);
-
   void OnAccountStorageOptInStateChanged();
 
   // Decides whether an authentication check is successful. Passes the result
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_browsertest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_browsertest.cc
index d110feb..ad6469bc 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_browsertest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_browsertest.cc
@@ -51,7 +51,7 @@
   PasswordsPrivateDelegateImpl delegate(browser()->profile());
 
   const GURL url(kUrl);
-  api::passwords_private::InsecureCredential credential;
+  api::passwords_private::PasswordUiEntry credential;
   credential.username = kUsername;
   credential.change_password_url = std::make_unique<std::string>(kUrl);
   base::MockCallback<
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
index adc2ff1..5511fc4b 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -780,73 +780,6 @@
   delegate.ExportPasswords(mock_accepted.Get(), nullptr);
 }
 
-// Verifies that PasswordsPrivateDelegateImpl::GetPlaintextInsecurePassword
-// fails if the re-auth fails.
-TEST_F(PasswordsPrivateDelegateImplTest,
-       TestReauthOnGetPlaintextInsecurePasswordFails) {
-  PasswordsPrivateDelegateImpl delegate(&profile_);
-
-  MockReauthCallback reauth_callback;
-  delegate.set_os_reauth_call(reauth_callback.Get());
-
-  base::MockCallback<
-      PasswordsPrivateDelegate::PlaintextInsecurePasswordCallback>
-      credential_callback;
-
-  EXPECT_CALL(reauth_callback, Run(ReauthPurpose::VIEW_PASSWORD, _))
-      .WillOnce(testing::WithArg<1>(
-          [&](password_manager::PasswordAccessAuthenticator::AuthResultCallback
-                  callback) { std::move(callback).Run(false); }));
-
-  EXPECT_CALL(credential_callback, Run(Eq(absl::nullopt)));
-
-  delegate.GetPlaintextInsecurePassword(
-      api::passwords_private::InsecureCredential(),
-      api::passwords_private::PLAINTEXT_REASON_VIEW, nullptr,
-      credential_callback.Get());
-}
-
-// Verifies that PasswordsPrivateDelegateImpl::GetPlaintextInsecurePassword
-// succeeds if the re-auth succeeds and there is a matching compromised
-// credential in the store.
-TEST_F(PasswordsPrivateDelegateImplTest, TestReauthOnGetPlaintextCompPassword) {
-  PasswordsPrivateDelegateImpl delegate(&profile_);
-
-  password_manager::PasswordForm form = CreateSampleForm();
-  form.password_issues = {
-      {password_manager::InsecureType::kLeaked,
-       password_manager::InsecurityMetadata(base::Time::FromTimeT(1),
-                                            password_manager::IsMuted(false))}};
-  profile_store_->AddLogin(form);
-  base::RunLoop().RunUntilIdle();
-
-  api::passwords_private::InsecureCredential credential =
-      std::move(delegate.GetCompromisedCredentials().at(0));
-
-  MockReauthCallback reauth_callback;
-  delegate.set_os_reauth_call(reauth_callback.Get());
-
-  base::MockCallback<
-      PasswordsPrivateDelegate::PlaintextInsecurePasswordCallback>
-      credential_callback;
-
-  absl::optional<api::passwords_private::InsecureCredential> opt_credential;
-  EXPECT_CALL(reauth_callback, Run(ReauthPurpose::VIEW_PASSWORD, _))
-      .WillOnce(testing::WithArg<1>(
-          [&](password_manager::PasswordAccessAuthenticator::AuthResultCallback
-                  callback) { std::move(callback).Run(true); }));
-  EXPECT_CALL(credential_callback, Run).WillOnce(MoveArg(&opt_credential));
-
-  delegate.GetPlaintextInsecurePassword(
-      std::move(credential), api::passwords_private::PLAINTEXT_REASON_VIEW,
-      nullptr, credential_callback.Get());
-
-  ASSERT_TRUE(opt_credential.has_value());
-  EXPECT_EQ(form.signon_realm, opt_credential->urls.signon_realm);
-  EXPECT_EQ(form.username_value, base::UTF8ToUTF16(opt_credential->username));
-  EXPECT_EQ(form.password_value, base::UTF8ToUTF16(*opt_credential->password));
-}
-
 TEST_F(PasswordsPrivateDelegateImplTest,
        GetUrlCollectionValueWithSchemeWhenIpAddress) {
   PasswordsPrivateDelegateImpl delegate(&profile_);
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
index 4a78041..c60acba 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
@@ -97,7 +97,7 @@
 }
 
 void PasswordsPrivateEventRouter::OnCompromisedCredentialsChanged(
-    std::vector<api::passwords_private::InsecureCredential>
+    std::vector<api::passwords_private::PasswordUiEntry>
         compromised_credentials) {
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_COMPROMISED_CREDENTIALS_INFO_CHANGED,
@@ -108,7 +108,7 @@
 }
 
 void PasswordsPrivateEventRouter::OnWeakCredentialsChanged(
-    std::vector<api::passwords_private::InsecureCredential> weak_credentials) {
+    std::vector<api::passwords_private::PasswordUiEntry> weak_credentials) {
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_WEAK_CREDENTIALS_CHANGED,
       api::passwords_private::OnWeakCredentialsChanged::kEventName,
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
index da0347e..a1dd2096 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
@@ -66,13 +66,13 @@
   // Notifies listeners about a change to the information about compromised
   // credentials.
   void OnCompromisedCredentialsChanged(
-      std::vector<api::passwords_private::InsecureCredential>
+      std::vector<api::passwords_private::PasswordUiEntry>
           compromised_credentials);
 
   // Notifies listeners about a change to the information about weak
   // credentials.
   void OnWeakCredentialsChanged(
-      std::vector<api::passwords_private::InsecureCredential> weak_credentials);
+      std::vector<api::passwords_private::PasswordUiEntry> weak_credentials);
 
   // Notifies listeners about a change to the status of the password check.
   void OnPasswordCheckStatusChanged(
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
index 012ffba57..b611ea8 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
@@ -6,6 +6,7 @@
 
 #include <tuple>
 
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/browser/ui/credential_ui_entry.h"
@@ -16,6 +17,7 @@
 namespace {
 
 using password_manager::CredentialUIEntry;
+using Store = password_manager::PasswordForm::Store;
 
 }  // namespace
 
@@ -37,4 +39,21 @@
   return urls;
 }
 
+extensions::api::passwords_private::PasswordStoreSet StoreSetFromCredential(
+    const CredentialUIEntry& credential) {
+  if (credential.stored_in.contains(Store::kAccountStore) &&
+      credential.stored_in.contains(Store::kProfileStore)) {
+    return extensions::api::passwords_private::
+        PASSWORD_STORE_SET_DEVICE_AND_ACCOUNT;
+  }
+  if (credential.stored_in.contains(Store::kAccountStore)) {
+    return extensions::api::passwords_private::PASSWORD_STORE_SET_ACCOUNT;
+  }
+  if (credential.stored_in.contains(Store::kProfileStore)) {
+    return extensions::api::passwords_private::PASSWORD_STORE_SET_DEVICE;
+  }
+  NOTREACHED();
+  return extensions::api::passwords_private::PASSWORD_STORE_SET_DEVICE;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
index 00282ad5..eca62db 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
@@ -33,6 +33,10 @@
 api::passwords_private::UrlCollection CreateUrlCollectionFromGURL(
     const GURL& url);
 
+// Returns PasswordStoreSet for |credential|.
+extensions::api::passwords_private::PasswordStoreSet StoreSetFromCredential(
+    const password_manager::CredentialUIEntry& credential);
+
 // This class is an id generator for an arbitrary key type. It is used by both
 // PasswordManagerPresenter and PasswordCheckDelegate to create ids send to the
 // UI. It is similar to base::IDMap, but has the following important
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
index 4630051b..c883996 100644
--- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
@@ -195,9 +195,9 @@
   is_opted_in_for_account_storage_ = opt_in;
 }
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 TestPasswordsPrivateDelegate::GetCompromisedCredentials() {
-  api::passwords_private::InsecureCredential credential;
+  api::passwords_private::PasswordUiEntry credential;
   credential.username = "alice";
   credential.urls.shown = "example.com";
   credential.urls.link = "https://example.com";
@@ -214,75 +214,43 @@
           TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, base::Days(3)));
   credential.compromised_info->compromise_type =
       api::passwords_private::COMPROMISE_TYPE_LEAKED;
-  std::vector<api::passwords_private::InsecureCredential> credentials;
+  credential.stored_in = api::passwords_private::PASSWORD_STORE_SET_DEVICE;
+  std::vector<api::passwords_private::PasswordUiEntry> credentials;
   credentials.push_back(std::move(credential));
   return credentials;
 }
 
-std::vector<api::passwords_private::InsecureCredential>
+std::vector<api::passwords_private::PasswordUiEntry>
 TestPasswordsPrivateDelegate::GetWeakCredentials() {
-  api::passwords_private::InsecureCredential credential;
+  api::passwords_private::PasswordUiEntry credential;
   credential.username = "bob";
   credential.urls.shown = "example.com";
   credential.urls.link = "https://example.com";
   credential.is_android_credential = false;
   credential.change_password_url =
       std::make_unique<std::string>("https://example.com/change-password");
-  std::vector<api::passwords_private::InsecureCredential> credentials;
+  credential.stored_in = api::passwords_private::PASSWORD_STORE_SET_DEVICE;
+  std::vector<api::passwords_private::PasswordUiEntry> credentials;
   credentials.push_back(std::move(credential));
   return credentials;
 }
 
-void TestPasswordsPrivateDelegate::GetPlaintextInsecurePassword(
-    api::passwords_private::InsecureCredential credential,
-    api::passwords_private::PlaintextReason reason,
-    content::WebContents* web_contents,
-    PlaintextInsecurePasswordCallback callback) {
-  // Return a mocked password value.
-  if (!plaintext_password_) {
-    std::move(callback).Run(absl::nullopt);
-    return;
-  }
-
-  credential.password =
-      std::make_unique<std::string>(base::UTF16ToUTF8(*plaintext_password_));
-  std::move(callback).Run(std::move(credential));
-}
-
-// Fake implementation of ChangeInsecureCredential. This succeeds if the
-// delegate knows of a insecure credential with the same id.
-bool TestPasswordsPrivateDelegate::ChangeInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential,
-    base::StringPiece new_password) {
-  return IsCredentialPresentInInsecureCredentialsList(credential);
-}
-
-// Fake implementation of RemoveInsecureCredential. This succeeds if the
-// delegate knows of a insecure credential with the same id.
-bool TestPasswordsPrivateDelegate::RemoveInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
-  return base::EraseIf(insecure_credentials_,
-                       [&credential](const auto& insecure_credential) {
-                         return insecure_credential.id == credential.id;
-                       }) != 0;
-}
-
 // Fake implementation of MuteInsecureCredential. This succeeds if the
 // delegate knows of a insecure credential with the same id.
 bool TestPasswordsPrivateDelegate::MuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   return IsCredentialPresentInInsecureCredentialsList(credential);
 }
 
 // Fake implementation of UnmuteInsecureCredential. This succeeds if the
 // delegate knows of a insecure credential with the same id.
 bool TestPasswordsPrivateDelegate::UnmuteInsecureCredential(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   return IsCredentialPresentInInsecureCredentialsList(credential);
 }
 
 void TestPasswordsPrivateDelegate::RecordChangePasswordFlowStarted(
-    const api::passwords_private::InsecureCredential& credential,
+    const api::passwords_private::PasswordUiEntry& credential,
     bool is_manual_flow) {
   last_change_flow_url_ =
       credential.change_password_url ? *credential.change_password_url : "";
@@ -304,7 +272,7 @@
 }
 
 void TestPasswordsPrivateDelegate::StartAutomatedPasswordChange(
-    const api::passwords_private::InsecureCredential& credential,
+    const api::passwords_private::PasswordUiEntry& credential,
     StartAutomatedPasswordChangeCallback callback) {
   std::move(callback).Run(credential.change_password_url &&
                           GURL(*credential.change_password_url).is_valid());
@@ -341,7 +309,7 @@
 }
 
 void TestPasswordsPrivateDelegate::AddCompromisedCredential(int id) {
-  api::passwords_private::InsecureCredential cred;
+  api::passwords_private::PasswordUiEntry cred;
   cred.id = id;
   insecure_credentials_.push_back(std::move(cred));
 }
@@ -361,7 +329,7 @@
 }
 
 bool TestPasswordsPrivateDelegate::IsCredentialPresentInInsecureCredentialsList(
-    const api::passwords_private::InsecureCredential& credential) {
+    const api::passwords_private::PasswordUiEntry& credential) {
   return std::any_of(insecure_credentials_.begin(), insecure_credentials_.end(),
                      [&credential](const auto& insecure_credential) {
                        return insecure_credential.id == credential.id;
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
index b4161f2..7894b9a8 100644
--- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
+++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
@@ -65,36 +65,22 @@
   bool IsOptedInForAccountStorage() override;
   void SetAccountStorageOptIn(bool opt_in,
                               content::WebContents* web_contents) override;
-  std::vector<api::passwords_private::InsecureCredential>
+  std::vector<api::passwords_private::PasswordUiEntry>
   GetCompromisedCredentials() override;
-  std::vector<api::passwords_private::InsecureCredential> GetWeakCredentials()
+  std::vector<api::passwords_private::PasswordUiEntry> GetWeakCredentials()
       override;
-  void GetPlaintextInsecurePassword(
-      api::passwords_private::InsecureCredential credential,
-      api::passwords_private::PlaintextReason reason,
-      content::WebContents* web_contents,
-      PlaintextInsecurePasswordCallback callback) override;
-  // Fake implementation of `ChangeInsecureCredential`. This succeeds if the
-  // delegate knows of a insecure credential with the same id.
-  bool ChangeInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential,
-      base::StringPiece new_password) override;
-  // Fake implementation of `RemoveInsecureCredential`. This succeeds if the
-  // delegate knows of a insecure credential with the same id.
-  bool RemoveInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
   // Fake implementation of `MuteInsecureCredential`. This succeeds if the
   // delegate knows of a insecure credential with the same id.
   bool MuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
+      const api::passwords_private::PasswordUiEntry& credential) override;
   // Fake implementation of `UnmuteInsecureCredential`. This succeeds if the
   // delegate knows of a insecure credential with the same id.
   bool UnmuteInsecureCredential(
-      const api::passwords_private::InsecureCredential& credential) override;
+      const api::passwords_private::PasswordUiEntry& credential) override;
   // Fake implementation of `RecordChangePasswordFlowStarted`. Sets the url
   // returned by `last_change_flow_url()`.
   void RecordChangePasswordFlowStarted(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       bool is_manual_flow) override;
   // Fake implementation of `RefreshScriptsIfNecessary` that directly calls
   // `callback`.
@@ -104,7 +90,7 @@
   void StopPasswordCheck() override;
   api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override;
   void StartAutomatedPasswordChange(
-      const api::passwords_private::InsecureCredential& credential,
+      const api::passwords_private::PasswordUiEntry& credential,
       StartAutomatedPasswordChangeCallback callback) override;
   password_manager::InsecureCredentialsManager* GetInsecureCredentialsManager()
       override;
@@ -142,7 +128,7 @@
   void SendSavedPasswordsList();
   void SendPasswordExceptionsList();
   bool IsCredentialPresentInInsecureCredentialsList(
-      const api::passwords_private::InsecureCredential& credential);
+      const api::passwords_private::PasswordUiEntry& credential);
   // The current list of entries/exceptions. Cached here so that when new
   // observers are added, this delegate can send the current lists without
   // having to request them from |password_manager_presenter_| again.
@@ -159,7 +145,7 @@
   absl::optional<std::u16string> plaintext_password_ = u"plaintext";
 
   // List of insecure credentials.
-  std::vector<api::passwords_private::InsecureCredential> insecure_credentials_;
+  std::vector<api::passwords_private::PasswordUiEntry> insecure_credentials_;
   raw_ptr<Profile> profile_ = nullptr;
 
   bool is_opted_in_for_account_storage_ = false;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index edc94ffb..e19dc6f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3866,7 +3866,7 @@
   {
     "name": "incognito-reauthentication-for-android",
     "owners": [ "roagarwal", "chrome-incognito@google.com" ],
-    "expiry_milestone": 105
+    "expiry_milestone": 110
   },
   {
     "name": "incognito-screenshot",
@@ -6524,7 +6524,7 @@
   {
     "name": "web-bundles",
     "owners": [ "//content/browser/web_package/OWNERS" ],
-    "expiry_milestone": 105
+    "expiry_milestone": 114
   },
   {
     "name": "web-feed",
diff --git a/chrome/browser/resources/chromeos/login/components/buttons/oobe_back_button.html b/chrome/browser/resources/chromeos/login/components/buttons/oobe_back_button.html
index 7ffa4bb..95f12d1d 100644
--- a/chrome/browser/resources/chromeos/login/components/buttons/oobe_back_button.html
+++ b/chrome/browser/resources/chromeos/login/components/buttons/oobe_back_button.html
@@ -50,10 +50,7 @@
   <template>
     <style include="cr-icons cr-shared-style oobe-common-styles">
       cr-button {
-        /*
-          TODO(https://crbug.com/1320715) Revise the color
-          --border-color: var(--oobe-button-border-color);
-        */
+        --border-color: var(--oobe-bg-color);
         --cr-button-height: var(--oobe-button-height);
         border-radius: var(--oobe-button-radius);
         margin: 0 4px;
diff --git a/chrome/browser/resources/chromeos/login/components/buttons/oobe_icon_button.html b/chrome/browser/resources/chromeos/login/components/buttons/oobe_icon_button.html
index d0d2cac..8127ee9 100644
--- a/chrome/browser/resources/chromeos/login/components/buttons/oobe_icon_button.html
+++ b/chrome/browser/resources/chromeos/login/components/buttons/oobe_icon_button.html
@@ -43,10 +43,7 @@
   <template>
     <style include="cr-icons cr-shared-style oobe-common-styles">
       cr-button {
-        /*
-          TODO(https://crbug.com/1320715) Revise the color
-          --border-color: var(--oobe-button-border-color);
-        */
+        --border-color: var(--oobe-bg-color);
         --cr-button-height: var(--oobe-button-height);
         border-radius: var(--oobe-button-radius);
         margin: 0 4px;
diff --git a/chrome/browser/resources/chromeos/login/screens/common/oobe_eula.html b/chrome/browser/resources/chromeos/login/screens/common/oobe_eula.html
index 5f98b4e4..4a74979 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/oobe_eula.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/oobe_eula.html
@@ -144,7 +144,7 @@
         </div>
       </div>
       <div slot="back-navigation">
-        <oobe-back-button hidden="[[backButtonHidden_]]"
+        <oobe-back-button id="backButton" hidden="[[backButtonHidden_]]"
             on-click="onEulaBackButtonPressed_"></oobe-back-button>
       </div>
       <div slot="bottom-buttons">
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.ts b/chrome/browser/resources/settings/autofill_page/password_check.ts
index e1727af..ee4538ef 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check.ts
@@ -209,7 +209,7 @@
   private showPasswordEditDialog_: boolean;
   private showPasswordRemoveDialog_: boolean;
   private showPasswordEditDisclaimer_: boolean;
-  private activePassword_: chrome.passwordsPrivate.InsecureCredential|null;
+  private activePassword_: chrome.passwordsPrivate.PasswordUiEntry|null;
   private showCompromisedCredentialsBody_: boolean;
   private showMutedPasswordsSection_: boolean;
   private showNoCompromisedPasswordsLabel_: boolean;
@@ -427,11 +427,12 @@
 
   private onEditPasswordClick_() {
     assert(this.activePassword_);
-    this.getPlaintextInsecurePassword(
-            this.activePassword_, chrome.passwordsPrivate.PlaintextReason.EDIT)
+    this.requestPlaintextPassword(
+            this.activePassword_.id,
+            chrome.passwordsPrivate.PlaintextReason.EDIT)
         .then(
-            insecureCredential => {
-              this.activePassword_ = insecureCredential;
+            password => {
+              this.activePassword_!.password = password;
               this.showPasswordEditDialog_ = true;
             },
             _error => {
@@ -851,8 +852,8 @@
     this.notifyPath('clickedChangePasswordIds_.size');
   }
 
-  private clickedChangePassword_(
-      item: chrome.passwordsPrivate.InsecureCredential): boolean {
+  private clickedChangePassword_(item: chrome.passwordsPrivate.PasswordUiEntry):
+      boolean {
     return this.clickedChangePasswordIds_.has(item.id);
   }
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
index 4df0a2d..404670d 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
@@ -72,7 +72,7 @@
     };
   }
 
-  item: chrome.passwordsPrivate.InsecureCredential|null;
+  item: chrome.passwordsPrivate.PasswordUiEntry|null;
   private visible: boolean;
   private inputInvalid_: boolean;
   private passwordManager_: PasswordManagerProxy =
@@ -104,8 +104,11 @@
     this.passwordManager_.recordPasswordCheckInteraction(
         PasswordCheckInteraction.EDIT_PASSWORD);
     assert(this.item);
-    this.passwordManager_
-        .changeInsecureCredential(this.item, this.$.passwordInput.value)
+    const params: chrome.passwordsPrivate.ChangeSavedPasswordParams = {
+      username: this.item.username,
+      password: this.$.passwordInput.value,
+    };
+    this.passwordManager_.changeSavedPassword(this.item.id, params)
         .finally(() => {
           this.close();
         });
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
index dc7f059..1951ffbc 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
@@ -88,7 +88,7 @@
     };
   }
 
-  item: chrome.passwordsPrivate.InsecureCredential;
+  item: chrome.passwordsPrivate.PasswordUiEntry;
   isPasswordVisible: boolean;
   private password_: string;
   clickedChangePassword: boolean;
@@ -188,9 +188,9 @@
   showPassword() {
     this.passwordManager_.recordPasswordCheckInteraction(
         PasswordCheckInteraction.SHOW_PASSWORD);
-    this.getPlaintextInsecurePassword(
-            this.item, chrome.passwordsPrivate.PlaintextReason.VIEW)
-        .then(insecureCredential => this.item = insecureCredential);
+    this.requestPlaintextPassword(
+            this.item.id, chrome.passwordsPrivate.PlaintextReason.VIEW)
+        .then(password => this.set('item.password', password), _error => {});
   }
 
   private onReadonlyInputTap_() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_mixin.ts b/chrome/browser/resources/settings/autofill_page/password_check_mixin.ts
index 1795b1a..7af6249 100644
--- a/chrome/browser/resources/settings/autofill_page/password_check_mixin.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_check_mixin.ts
@@ -93,9 +93,9 @@
         }
 
         passwordManager: PasswordManagerProxy|null = null;
-        leakedPasswords: chrome.passwordsPrivate.InsecureCredential[];
-        mutedPasswords: chrome.passwordsPrivate.InsecureCredential[];
-        weakPasswords: chrome.passwordsPrivate.InsecureCredential[];
+        leakedPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
+        mutedPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
+        weakPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
         compromisedPasswordsCount: string;
         weakPasswordsCount: string;
         insecurePasswordsCount: string;
@@ -201,7 +201,7 @@
          * entities should appear in the bottom.
          */
         updateCompromisedPasswordList(
-            newList: chrome.passwordsPrivate.InsecureCredential[]) {
+            newList: chrome.passwordsPrivate.PasswordUiEntry[]) {
           if (this.isMutedPasswordsEnabled) {
             this.updateLeakedAndMutedPasswordLists(newList);
             return;
@@ -211,9 +211,9 @@
         }
 
         private updateLeakedAndMutedPasswordLists(
-            newList: chrome.passwordsPrivate.InsecureCredential[]) {
+            newList: chrome.passwordsPrivate.PasswordUiEntry[]) {
           const isMutedPredicate =
-              (item: chrome.passwordsPrivate.InsecureCredential) =>
+              (item: chrome.passwordsPrivate.PasswordUiEntry) =>
                   !!item.compromisedInfo && item.compromisedInfo.isMuted;
           this.leakedPasswords = this.createCombinedCompromisedPasswordList(
               this.leakedPasswords,
@@ -223,12 +223,12 @@
         }
 
         private createCombinedCompromisedPasswordList(
-            oldList: chrome.passwordsPrivate.InsecureCredential[],
-            newList: chrome.passwordsPrivate.InsecureCredential[]):
-            chrome.passwordsPrivate.InsecureCredential[] {
+            oldList: chrome.passwordsPrivate.PasswordUiEntry[],
+            newList: chrome.passwordsPrivate.PasswordUiEntry[]):
+            chrome.passwordsPrivate.PasswordUiEntry[] {
           const map = new Map(newList.map(item => ([item.id, item])));
 
-          const resultList: chrome.passwordsPrivate.InsecureCredential[] = [];
+          const resultList: chrome.passwordsPrivate.PasswordUiEntry[] = [];
 
           for (const item of oldList) {
             // If element is present in newList
@@ -242,9 +242,8 @@
           const addedResults = Array.from(map.values());
           addedResults.sort((lhs, rhs) => {
             // Phished passwords are always shown above leaked passwords.
-            const isPhished =
-                (cred: chrome.passwordsPrivate.InsecureCredential) =>
-                    cred.compromisedInfo!.compromiseType !==
+            const isPhished = (cred: chrome.passwordsPrivate.PasswordUiEntry) =>
+                cred.compromisedInfo!.compromiseType !==
                 chrome.passwordsPrivate.CompromiseType.LEAKED;
             if (isPhished(lhs) !== isPhished(rhs)) {
               return isPhished(lhs) ? -1 : 1;
@@ -273,9 +272,9 @@
 
 export interface PasswordCheckMixinInterface {
   passwordManager: PasswordManagerProxy|null;
-  leakedPasswords: chrome.passwordsPrivate.InsecureCredential[];
-  mutedPasswords: chrome.passwordsPrivate.InsecureCredential[];
-  weakPasswords: chrome.passwordsPrivate.InsecureCredential[];
+  leakedPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
+  mutedPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
+  weakPasswords: chrome.passwordsPrivate.PasswordUiEntry[];
   compromisedPasswordsCount: string;
   weakPasswordsCount: string;
   insecurePasswordsCount: string;
@@ -283,5 +282,5 @@
   isInitialStatus: boolean;
   isMutedPasswordsEnabled: boolean;
   updateCompromisedPasswordList(
-      newList: chrome.passwordsPrivate.InsecureCredential[]): void;
+      newList: chrome.passwordsPrivate.PasswordUiEntry[]): void;
 }
diff --git a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts
index 62fe077..99c34278 100644
--- a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts
@@ -7,7 +7,7 @@
  * chrome.passwordsPrivate which facilitates testing.
  */
 
-type InsecureCredentials = chrome.passwordsPrivate.InsecureCredential[];
+type InsecureCredentials = chrome.passwordsPrivate.PasswordUiEntry[];
 export type SavedPasswordListChangedListener =
     (entries: chrome.passwordsPrivate.PasswordUiEntry[]) => void;
 export type PasswordExceptionListChangedListener =
@@ -235,32 +235,26 @@
    * @param credential The credential for which to start the flow.
    */
   startAutomatedPasswordChange(
-      credential: chrome.passwordsPrivate.InsecureCredential): Promise<boolean>;
-
-  /**
-   * Requests to remove |insecureCredential| from the password store.
-   */
-  removeInsecureCredential(
-      insecureCredential: chrome.passwordsPrivate.InsecureCredential): void;
+      credential: chrome.passwordsPrivate.PasswordUiEntry): Promise<boolean>;
 
   /**
    * Dismisses / mutes the |insecureCredential| in the passwords store.
    */
   muteInsecureCredential(insecureCredential:
-                             chrome.passwordsPrivate.InsecureCredential): void;
+                             chrome.passwordsPrivate.PasswordUiEntry): void;
 
   /**
    * Restores / unmutes the |insecureCredential| in the passwords store.
    */
-  unmuteInsecureCredential(
-      insecureCredential: chrome.passwordsPrivate.InsecureCredential): void;
+  unmuteInsecureCredential(insecureCredential:
+                               chrome.passwordsPrivate.PasswordUiEntry): void;
 
   /**
    * Records the state of a change password flow for |insecureCredential|
    * and notes it is a manual flow via |isManualFlow|.
    */
   recordChangePasswordFlowStarted(
-      insecureCredential: chrome.passwordsPrivate.InsecureCredential,
+      insecureCredential: chrome.passwordsPrivate.PasswordUiEntry,
       isManualFlow: boolean): void;
 
   /**
@@ -297,25 +291,6 @@
       listener: PasswordCheckStatusChangedListener): void;
 
   /**
-   * Requests the plaintext password for |credential|. |callback| gets invoked
-   * with the same |credential|, whose |password| field will be set.
-   * @return A promise that resolves to the InsecureCredential with the password
-   *     field populated.
-   */
-  getPlaintextInsecurePassword(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      reason: chrome.passwordsPrivate.PlaintextReason):
-      Promise<chrome.passwordsPrivate.InsecureCredential>;
-
-  /**
-   * Requests to change the password of |credential| to |new_password|.
-   * @return A promise that resolves when the password is updated.
-   */
-  changeInsecureCredential(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      newPassword: string): Promise<void>;
-
-  /**
    * Records a given interaction on the Password Check page.
    */
   recordPasswordCheckInteraction(interaction: PasswordCheckInteraction): void;
@@ -535,7 +510,7 @@
   }
 
   startAutomatedPasswordChange(credential:
-                                   chrome.passwordsPrivate.InsecureCredential) {
+                                   chrome.passwordsPrivate.PasswordUiEntry) {
     return new Promise<boolean>(resolve => {
       chrome.passwordsPrivate.startAutomatedPasswordChange(credential, resolve);
     });
@@ -579,23 +554,18 @@
     });
   }
 
-  removeInsecureCredential(insecureCredential:
-                               chrome.passwordsPrivate.InsecureCredential) {
-    chrome.passwordsPrivate.removeInsecureCredential(insecureCredential);
-  }
-
   muteInsecureCredential(insecureCredential:
-                             chrome.passwordsPrivate.InsecureCredential) {
+                             chrome.passwordsPrivate.PasswordUiEntry) {
     chrome.passwordsPrivate.muteInsecureCredential(insecureCredential);
   }
 
   unmuteInsecureCredential(insecureCredential:
-                               chrome.passwordsPrivate.InsecureCredential) {
+                               chrome.passwordsPrivate.PasswordUiEntry) {
     chrome.passwordsPrivate.unmuteInsecureCredential(insecureCredential);
   }
 
   recordChangePasswordFlowStarted(
-      insecureCredential: chrome.passwordsPrivate.InsecureCredential,
+      insecureCredential: chrome.passwordsPrivate.PasswordUiEntry,
       isManualFlow: boolean) {
     chrome.passwordsPrivate.recordChangePasswordFlowStarted(
         insecureCredential, isManualFlow);
@@ -629,32 +599,6 @@
         listener);
   }
 
-  getPlaintextInsecurePassword(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      reason: chrome.passwordsPrivate.PlaintextReason) {
-    return new Promise<chrome.passwordsPrivate.InsecureCredential>(
-        (resolve, reject) => {
-          chrome.passwordsPrivate.getPlaintextInsecurePassword(
-              credential, reason, credentialWithPassword => {
-                if (chrome.runtime.lastError) {
-                  reject(chrome.runtime.lastError.message);
-                  return;
-                }
-
-                resolve(credentialWithPassword);
-              });
-        });
-  }
-
-  changeInsecureCredential(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      newPassword: string) {
-    return new Promise<void>(resolve => {
-      chrome.passwordsPrivate.changeInsecureCredential(
-          credential, newPassword, resolve);
-    });
-  }
-
   /** override */
   recordPasswordCheckInteraction(interaction: PasswordCheckInteraction) {
     chrome.metricsPrivate.recordEnumerationValue(
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts
index e7503e741..806cd36 100644
--- a/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts
@@ -46,7 +46,7 @@
     };
   }
 
-  item: chrome.passwordsPrivate.InsecureCredential;
+  item: chrome.passwordsPrivate.PasswordUiEntry;
   private passwordManager_: PasswordManagerProxy =
       PasswordManagerImpl.getInstance();
 
@@ -59,7 +59,7 @@
   private onRemoveClick_() {
     this.passwordManager_.recordPasswordCheckInteraction(
         PasswordCheckInteraction.REMOVE_PASSWORD);
-    this.passwordManager_.removeInsecureCredential(this.item);
+    this.passwordManager_.removeSavedPassword(this.item.id, this.item.storedIn);
     this.$.dialog.close();
   }
 
diff --git a/chrome/browser/resources/settings/autofill_page/password_requestor_mixin.ts b/chrome/browser/resources/settings/autofill_page/password_requestor_mixin.ts
index 3b4775e..5dd0b28f 100644
--- a/chrome/browser/resources/settings/autofill_page/password_requestor_mixin.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_requestor_mixin.ts
@@ -43,25 +43,6 @@
               id, reason);
           // </if>
         }
-
-        getPlaintextInsecurePassword(
-            credential: chrome.passwordsPrivate.InsecureCredential,
-            reason: chrome.passwordsPrivate.PlaintextReason):
-            Promise<chrome.passwordsPrivate.InsecureCredential> {
-          return new Promise(resolve => {
-            PasswordManagerImpl.getInstance()
-                .getPlaintextInsecurePassword(credential, reason)
-                .then(insecureCredential => resolve(insecureCredential), () => {
-                  // <if expr="chromeos_ash or chromeos_lacros">
-                  // If no password was found, refresh auth token and retry.
-                  this.tokenRequestManager.request(() => {
-                    this.getPlaintextInsecurePassword(credential, reason)
-                        .then(resolve);
-                  });
-                  // </if>
-                });
-          });
-        }
       }
 
       return PasswordRequestorMixin;
@@ -71,10 +52,6 @@
   requestPlaintextPassword(
       id: number,
       reason: chrome.passwordsPrivate.PlaintextReason): Promise<string>;
-  getPlaintextInsecurePassword(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      reason: chrome.passwordsPrivate.PlaintextReason):
-      Promise<chrome.passwordsPrivate.InsecureCredential>;
   // <if expr="chromeos_ash or chromeos_lacros">
   tokenRequestManager: BlockingRequestManager;
   // </if>
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 8345f4a..90bf925 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -67,7 +67,7 @@
       "chrome://resources/js/cr.m.js",
       "chrome://resources/mojo/ash/services/cellular_setup/public/mojom/cellular_setup.mojom-lite.js",
       "chrome://resources/mojo/ash/services/cellular_setup/public/mojom/esim_manager.mojom-lite.js",
-      "chrome://resources/mojo/chromeos/ash/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js",
+      "chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js",
       "chrome://resources/mojo/chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js",
       "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-lite.js",
       "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js",
diff --git a/chrome/browser/resources/tools/optimize_webui.py b/chrome/browser/resources/tools/optimize_webui.py
index ce857d27..17d94213 100755
--- a/chrome/browser/resources/tools/optimize_webui.py
+++ b/chrome/browser/resources/tools/optimize_webui.py
@@ -187,8 +187,6 @@
           'Unexpected <if expr> found in bundled output. Check that all ' + \
           'input files using such expressions are preprocessed.'
 
-  return bundled_paths
-
 
 def _optimize(in_folder, args):
   in_path = os.path.normpath(os.path.join(_CWD, in_folder)).replace('\\', '/')
@@ -211,15 +209,8 @@
   external_paths = args.external_paths or []
 
   try:
-    pcb_out_paths = [os.path.join(tmp_out_dir, f) for f in args.js_out_files]
-    bundled_paths = _bundle_v3(tmp_out_dir, in_path, out_path,
-                               manifest_out_path, args, excludes,
-                               external_paths)
-
-    # Run polymer-css-build.
-    node.RunNode([node_modules.PathToPolymerCssBuild()] +
-                 ['--polymer-version', '2'] + ['--no-inline-includes', '-f'] +
-                 bundled_paths + ['-o'] + pcb_out_paths)
+    _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args,
+               excludes, external_paths)
 
     # Pass the JS files through Terser and write the output to its final
     # destination.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index e84c25c..97d32bf 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3159,6 +3159,7 @@
       "//chromeos/ash/components/network",
       "//chromeos/ash/components/network/portal_detector",
       "//chromeos/ash/components/oobe_quick_start",
+      "//chromeos/ash/components/string_matching",
       "//chromeos/ash/resources",
       "//chromeos/ash/services/assistant:lib",
       "//chromeos/ash/services/assistant/public/cpp",
@@ -3170,7 +3171,6 @@
       "//chromeos/components/quick_answers/public/cpp:cpp",
       "//chromeos/components/quick_answers/public/cpp:prefs",
       "//chromeos/components/sharesheet:constants",
-      "//chromeos/components/string_matching",
       "//chromeos/constants",
       "//chromeos/crosapi/cpp",
       "//chromeos/crosapi/cpp:crosapi_constants",
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index d7ce03fc..f141518e 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -43,9 +43,9 @@
 #include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "components/sync/base/model_type.h"
@@ -54,8 +54,14 @@
 #include "content/public/browser/browser_thread.h"
 #include "ui/chromeos/devicetype_utils.h"
 
+namespace app_list {
+
 namespace {
 
+using ::ash::string_matching::FuzzyTokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedStringMatch;
+
 constexpr double kEps = 1e-5;
 
 // The minimum capacity we reserve in the Apps container which will be filled
@@ -73,10 +79,6 @@
     web_app::kOsSettingsAppId, web_app::kHelpAppId, arc::kPlayStoreAppId,
     web_app::kCanvasAppId, web_app::kCameraAppId};
 
-using chromeos::string_matching::FuzzyTokenizedStringMatch;
-using chromeos::string_matching::TokenizedString;
-using chromeos::string_matching::TokenizedStringMatch;
-
 // A selection of apps are designated as default recommended apps, and these are
 // ranked in a priority order. Determine the rank of the app corresponding to
 // |app_id|.
@@ -95,8 +97,8 @@
 // Adds |app_result| to |results| only in case no duplicate apps were already
 // added. Duplicate means the same app but for different domain, Chrome and
 // Android.
-void MaybeAddResult(app_list::SearchProvider::Results* results,
-                    std::unique_ptr<app_list::AppResult> app_result,
+void MaybeAddResult(SearchProvider::Results* results,
+                    std::unique_ptr<AppResult> app_result,
                     std::set<std::string>* seen_or_filtered_apps) {
   if (seen_or_filtered_apps->count(app_result->app_id()))
     return;
@@ -149,8 +151,6 @@
 
 }  // namespace
 
-namespace app_list {
-
 class AppSearchProvider::App {
  public:
   App(AppSearchProvider::DataSource* data_source,
diff --git a/chrome/browser/ui/app_list/search/files/drive_search_provider.cc b/chrome/browser/ui/app_list/search/files/drive_search_provider.cc
index 4e6d0d9..9ce289cc 100644
--- a/chrome/browser/ui/app_list/search/files/drive_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/files/drive_search_provider.cc
@@ -24,9 +24,10 @@
 #include "url/gurl.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedString;
 
 constexpr char kDriveSearchSchema[] = "drive_search://";
 constexpr int kMaxResults = 50;
diff --git a/chrome/browser/ui/app_list/search/files/drive_search_provider.h b/chrome/browser/ui/app_list/search/files/drive_search_provider.h
index 853b76e..fc1995e 100644
--- a/chrome/browser/ui/app_list/search/files/drive_search_provider.h
+++ b/chrome/browser/ui/app_list/search/files/drive_search_provider.h
@@ -14,7 +14,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/ui/app_list/search/files/file_result.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "components/drive/file_errors.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -64,8 +64,7 @@
 
   base::TimeTicks query_start_time_;
   std::u16string last_query_;
-  absl::optional<chromeos::string_matching::TokenizedString>
-      last_tokenized_query_;
+  absl::optional<ash::string_matching::TokenizedString> last_tokenized_query_;
 
   Profile* const profile_;
   drive::DriveIntegrationService* const drive_service_;
diff --git a/chrome/browser/ui/app_list/search/files/file_result.cc b/chrome/browser/ui/app_list/search/files/file_result.cc
index bac2b22..bda617d 100644
--- a/chrome/browser/ui/app_list/search/files/file_result.cc
+++ b/chrome/browser/ui/app_list/search/files/file_result.cc
@@ -25,7 +25,8 @@
 #include "chrome/browser/ui/app_list/search/files/justifications.h"
 #include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "chrome/browser/ui/ash/thumbnail_loader.h"
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "chromeos/ui/base/file_icon_util.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
@@ -35,8 +36,8 @@
 
 namespace {
 
-using chromeos::string_matching::TokenizedString;
-using chromeos::string_matching::TokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedStringMatch;
 
 // The default relevance returned by CalculateRelevance.
 constexpr double kDefaultRelevance = 0.5;
diff --git a/chrome/browser/ui/app_list/search/files/file_result.h b/chrome/browser/ui/app_list/search/files/file_result.h
index ddf4a09..c07b6f3 100644
--- a/chrome/browser/ui/app_list/search/files/file_result.h
+++ b/chrome/browser/ui/app_list/search/files/file_result.h
@@ -11,7 +11,6 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -19,6 +18,9 @@
 
 namespace ash {
 class ThumbnailLoader;
+namespace string_matching {
+class TokenizedString;
+}
 }
 
 namespace app_list {
@@ -50,7 +52,7 @@
   // Calculates file's match relevance score. Will return a default score if the
   // query is missing or the filename is empty.
   static double CalculateRelevance(
-      const absl::optional<chromeos::string_matching::TokenizedString>& query,
+      const absl::optional<ash::string_matching::TokenizedString>& query,
       const base::FilePath& filepath,
       const absl::optional<base::Time>& last_accessed);
 
diff --git a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc b/chrome/browser/ui/app_list/search/files/file_result_unittest.cc
index 8daf0b0a..0b075a37 100644
--- a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/files/file_result_unittest.cc
@@ -14,17 +14,18 @@
 #include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::TokenizedString;
-using testing::DoubleNear;
+using ::ash::string_matching::TokenizedString;
+using ::testing::DoubleNear;
 
 }  // namespace
 
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider.cc b/chrome/browser/ui/app_list/search/files/file_search_provider.cc
index 8b6a96c85..0341cbdd 100644
--- a/chrome/browser/ui/app_list/search/files/file_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/files/file_search_provider.cc
@@ -22,9 +22,10 @@
 #include "ui/base/l10n/l10n_util.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedString;
 
 constexpr char kFileSearchSchema[] = "file_search://";
 constexpr int kMaxResults = 25;
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider.h b/chrome/browser/ui/app_list/search/files/file_search_provider.h
index ce91176..f29fcfe2 100644
--- a/chrome/browser/ui/app_list/search/files/file_search_provider.h
+++ b/chrome/browser/ui/app_list/search/files/file_search_provider.h
@@ -14,7 +14,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 #include "chrome/browser/ui/ash/thumbnail_loader.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -60,8 +60,7 @@
 
   base::TimeTicks query_start_time_;
   std::u16string last_query_;
-  absl::optional<chromeos::string_matching::TokenizedString>
-      last_tokenized_query_;
+  absl::optional<ash::string_matching::TokenizedString> last_tokenized_query_;
 
   Profile* const profile_;
   ash::ThumbnailLoader thumbnail_loader_;
diff --git a/chrome/browser/ui/app_list/search/games/game_provider.cc b/chrome/browser/ui/app_list/search/games/game_provider.cc
index 8b78ebe..71eb57b 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider.cc
+++ b/chrome/browser/ui/app_list/search/games/game_provider.cc
@@ -22,16 +22,17 @@
 #include "chrome/browser/ui/app_list/search/games/game_result.h"
 #include "chrome/browser/ui/app_list/search/search_features.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::FuzzyTokenizedStringMatch;
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::FuzzyTokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
 
 // Parameters for FuzzyTokenizedStringMatch.
 constexpr bool kUseWeightedRatio = false;
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.cc
index aac3e6eb..dca81113 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.cc
@@ -15,12 +15,13 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/keyboard_shortcut_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 
 namespace app_list {
 
 namespace {
 
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedString;
 
 constexpr size_t kMinQueryLength = 3u;
 constexpr size_t kMaxResults = 3u;
@@ -29,8 +30,7 @@
 std::vector<std::pair<KeyboardShortcutData, double>> Search(
     const std::vector<KeyboardShortcutData>& shortcut_data,
     std::u16string query) {
-  chromeos::string_matching::TokenizedString tokenized_query(
-      query, TokenizedString::Mode::kWords);
+  TokenizedString tokenized_query(query, TokenizedString::Mode::kWords);
 
   // Find all shortcuts which meet the relevance threshold.
   std::vector<std::pair<KeyboardShortcutData, double>> candidates;
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h
index 1d941132..6ac9fbc 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h
@@ -9,7 +9,6 @@
 #include "base/sequence_checker.h"
 #include "chrome/browser/ui/app_list/search/keyboard_shortcut_data.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
 
 class Profile;
 
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
index 9644237..5a62c443 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
@@ -18,7 +18,8 @@
 #include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/app_list/search/common/search_result_util.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/features.h"
@@ -30,13 +31,11 @@
 
 namespace {
 
-using chromeos::string_matching::TokenizedString;
-using chromeos::string_matching::TokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedStringMatch;
 using TextVector = ChromeSearchResult::TextVector;
-using TextItem = ash::SearchResultTextItem;
-using TextType = ash::SearchResultTextItemType;
-using IconCode = ash::SearchResultTextItem::IconCode;
-using KeyboardCode = ui::KeyboardCode;
+using IconCode = ::ash::SearchResultTextItem::IconCode;
+using ::ui::KeyboardCode;
 
 constexpr char kKeyboardShortcutScheme[] = "keyboard_shortcut://";
 
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.h b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.h
index e629faf..38bce08 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.h
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.h
@@ -8,7 +8,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/keyboard_shortcut_data.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+
+namespace ash::string_matching {
+class TokenizedString;
+}
 
 namespace app_list {
 
@@ -28,7 +31,7 @@
   // Calculates the shortcut's relevance score. Will return a default score if
   // the query is missing or the target is empty.
   static double CalculateRelevance(
-      const chromeos::string_matching::TokenizedString& query_tokenized,
+      const ash::string_matching::TokenizedString& query_tokenized,
       const std::u16string& target);
 
  private:
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc
index 499a404..2a89d47 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -18,14 +18,11 @@
 #include "ui/events/keycodes/keyboard_codes_posix.h"
 
 namespace app_list {
-namespace {
 
-using chromeos::string_matching::TokenizedString;
-using ui::KeyboardCode;
+using ::ash::string_matching::TokenizedString;
+using ::ui::KeyboardCode;
 using TextVector = ChromeSearchResult::TextVector;
-using TextType = ash::SearchResultTextItemType;
-
-}  // namespace
+using TextType = ::ash::SearchResultTextItemType;
 
 class KeyboardShortcutResultTest : public testing::Test {
  public:
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc
index 01dd680..347be4c 100644
--- a/chrome/browser/ui/app_list/search/omnibox_provider.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -37,9 +37,10 @@
 #include "url/gurl.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedString;
 
 // Some omnibox answers overtrigger on short queries. This controls the minimum
 // query length before they are displayed.
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.h b/chrome/browser/ui/app_list/search/omnibox_provider.h
index 2b85e01..f7407dd 100644
--- a/chrome/browser/ui/app_list/search/omnibox_provider.h
+++ b/chrome/browser/ui/app_list/search/omnibox_provider.h
@@ -9,7 +9,7 @@
 
 #include "base/time/time.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "components/omnibox/browser/autocomplete_controller.h"
 #include "components/omnibox/browser/favicon_cache.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -54,8 +54,7 @@
   AppListControllerDelegate* list_controller_;
 
   std::u16string last_query_;
-  absl::optional<chromeos::string_matching::TokenizedString>
-      last_tokenized_query_;
+  absl::optional<ash::string_matching::TokenizedString> last_tokenized_query_;
   base::TimeTicks query_start_time_;
   AutocompleteInput input_;
 
diff --git a/chrome/browser/ui/app_list/search/open_tab_result.cc b/chrome/browser/ui/app_list/search/open_tab_result.cc
index 4e9daa8..63483811 100644
--- a/chrome/browser/ui/app_list/search/open_tab_result.cc
+++ b/chrome/browser/ui/app_list/search/open_tab_result.cc
@@ -16,7 +16,8 @@
 #include "chrome/browser/ui/app_list/search/common/string_util.h"
 #include "chrome/browser/ui/app_list/search/omnibox_util.h"
 #include "chrome/browser/ui/app_list/search/search_tags_util.h"
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_match_type.h"
 #include "components/omnibox/browser/favicon_cache.h"
@@ -28,10 +29,11 @@
 #include "url/gurl.h"
 
 namespace app_list {
+
 namespace {
 
-using chromeos::string_matching::TokenizedString;
-using chromeos::string_matching::TokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedStringMatch;
 
 constexpr char kOpenTabScheme[] = "opentab://";
 
diff --git a/chrome/browser/ui/app_list/search/open_tab_result.h b/chrome/browser/ui/app_list/search/open_tab_result.h
index a2f51807..e9672797 100644
--- a/chrome/browser/ui/app_list/search/open_tab_result.h
+++ b/chrome/browser/ui/app_list/search/open_tab_result.h
@@ -8,7 +8,6 @@
 #include "ash/public/cpp/style/color_mode_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -16,6 +15,10 @@
 class FaviconCache;
 class Profile;
 
+namespace ash::string_matching {
+class TokenizedString;
+}
+
 namespace app_list {
 
 // Open tab search results. This is produced by the OmniboxProvider.
@@ -24,7 +27,7 @@
   OpenTabResult(Profile* profile,
                 AppListControllerDelegate* list_controller,
                 FaviconCache* favicon_cache,
-                const chromeos::string_matching::TokenizedString& query,
+                const ash::string_matching::TokenizedString& query,
                 const AutocompleteMatch& match);
   ~OpenTabResult() override;
 
diff --git a/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc b/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
index 9bef83f..90d3541d 100644
--- a/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/open_tab_result_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/app_list/search/common/search_result_util.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_match_type.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -16,11 +17,8 @@
 #include "url/gurl.h"
 
 namespace app_list {
-namespace {
 
-using chromeos::string_matching::TokenizedString;
-
-}  //  namespace
+using ::ash::string_matching::TokenizedString;
 
 class OpenTabResultTest : public testing::Test {
  public:
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
index 9063f5b..4862f541 100644
--- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -186,9 +186,9 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  std::vector<extensions::api::passwords_private::InsecureCredential>
+  std::vector<extensions::api::passwords_private::PasswordUiEntry>
   GetCompromisedCredentials() override {
-    std::vector<extensions::api::passwords_private::InsecureCredential>
+    std::vector<extensions::api::passwords_private::PasswordUiEntry>
         compromised(compromised_password_count_);
     for (int i = 0; i < compromised_password_count_; ++i) {
       compromised[i].username = "test" + base::NumberToString(i);
@@ -196,9 +196,9 @@
     return compromised;
   }
 
-  std::vector<extensions::api::passwords_private::InsecureCredential>
+  std::vector<extensions::api::passwords_private::PasswordUiEntry>
   GetWeakCredentials() override {
-    std::vector<extensions::api::passwords_private::InsecureCredential> weak(
+    std::vector<extensions::api::passwords_private::PasswordUiEntry> weak(
         weak_password_count_);
     for (int i = 0; i < weak_password_count_; ++i) {
       weak[i].username = "test" + base::NumberToString(i);
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index fdc6e96..f4ba5ba60 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1658793396-2b3e91d50dec89dc5f964c378ad2211d69f34f79.profdata
+chrome-linux-main-1658815016-2a812b4449b0676d2b93df25a0be62ffe78bbb52.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index cef17f8..421fbfaa 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1658771855-538ceb72d7f9bdf56917ebcb768fe5e716b0ac83.profdata
+chrome-mac-main-1658815016-680ffa5ecbbac616bad83e8fe2a117966e82c5cf.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 73eaa8a..4627502b 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1658782695-800f94790381496901cbb518b4b29339c2060272.profdata
+chrome-win32-main-1658815016-5cc1eff7f626005846b4cdf8301af64e6b760f5d.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 1a85403..fa1b3e7 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1658782695-1e7ad3e3542b9180a1af0f81cfcbaa527a0ed821.profdata
+chrome-win64-main-1658825963-e56af5874320c55143fa10595452211b7da67555.profdata
diff --git a/chrome/common/extensions/api/passwords_private.idl b/chrome/common/extensions/api/passwords_private.idl
index 1896583..a8479343 100644
--- a/chrome/common/extensions/api/passwords_private.idl
+++ b/chrome/common/extensions/api/passwords_private.idl
@@ -128,6 +128,25 @@
     DOMString link;
   };
 
+  // Information specific to compromised credentials.
+  dictionary CompromisedInfo {
+    // The timestamp of when this credential was determined to be compromised.
+    // Specified in milliseconds since the UNIX epoch. Intended to be passed to
+    // the JavaScript Date() constructor.
+    double compromiseTime;
+
+    // The elapsed time since this credential was determined to be compromised.
+    // This is passed as an already formatted string, since JavaScript lacks the
+    // required formatting APIs. Example: "5 minutes ago"
+    DOMString elapsedTimeSinceCompromise;
+
+    // The type of the credentials that was compromised.
+    CompromiseType compromiseType;
+
+    // Indicates whether this credential is muted.
+    boolean isMuted;
+  };
+
   // Entry used to display a password in the settings UI.
   dictionary PasswordUiEntry {
     // The URL collection corresponding to this saved password entry.
@@ -154,6 +173,17 @@
 
     // The value of the attached note.
     DOMString note;
+
+    // The URL where the insecure password can be changed. Might be not set for
+    // Android apps.
+    DOMString? changePasswordUrl;
+
+    // Indicates whether a script exists to change this credential
+    // automatically.
+    boolean hasStartableScript;
+
+    // Additional information in case a credential is compromised.
+    CompromisedInfo? compromisedInfo;
   };
 
   dictionary ExceptionEntry {
@@ -173,58 +203,6 @@
     DOMString? folderName;
   };
 
-  // Information specific to compromised credentials.
-  dictionary CompromisedInfo {
-    // The timestamp of when this credential was determined to be compromised.
-    // Specified in milliseconds since the UNIX epoch. Intended to be passed to
-    // the JavaScript Date() constructor.
-    double compromiseTime;
-
-    // The elapsed time since this credential was determined to be compromised.
-    // This is passed as an already formatted string, since JavaScript lacks the
-    // required formatting APIs. Example: "5 minutes ago"
-    DOMString elapsedTimeSinceCompromise;
-
-    // The type of the credentials that was compromised.
-    CompromiseType compromiseType;
-
-    // Indicates whether this credential is muted.
-    boolean isMuted;
-  };
-
-  // Information about an insecure credential and relevant information required
-  // for the display in the UI.
-  dictionary InsecureCredential {
-    // The URL collection corresponding to this insecure credential.
-    UrlCollection urls;
-
-    // An id serving as a mapping to a given insecure credential. This
-    // identifier will remain stable for a single browser session.
-    long id;
-
-    // Indicates whether this credential belongs to an Android app.
-    boolean isAndroidCredential;
-
-    // The URL where the insecure password can be changed. Might be not set for
-    // Android apps.
-    DOMString? changePasswordUrl;
-
-    // Indicates whether a script exists to change this credential
-    // automatically.
-    boolean hasStartableScript;
-
-    // The username of the credential.
-    DOMString username;
-
-    // The password of the credential. Initially empty, only set if explicitly
-    // requested.
-    DOMString? password;
-
-    // Additional information in case a credential is compromised (i.e. phished
-    // or leaked).
-    CompromisedInfo? compromisedInfo;
-  };
-
   // Object describing the current state of the password check. The check could
   // be in any of the above described states.
   dictionary PasswordCheckStatus {
@@ -282,10 +260,6 @@
   callback ExportProgressStatusCallback = void(ExportProgressStatus status);
   callback VoidCallback = void();
   callback OptInCallback = void(boolean optedIn);
-  callback InsecureCredentialsCallback =
-      void(InsecureCredential[] insecureCredentials);
-  callback GetPlaintextInsecurePasswordCallback =
-      void(InsecureCredential credential);
   callback PasswordCheckStatusCallback = void(PasswordCheckStatus status);
   callback StartAutomatedPasswordChangeCallback = void(boolean success);
   callback ImportPasswordsCallback = void(ImportResults results);
@@ -385,55 +359,28 @@
 
     // Requests the latest compromised credentials.
     [supportsPromises] static void getCompromisedCredentials(
-        InsecureCredentialsCallback callback);
+        PasswordListCallback callback);
 
     // Requests the latest weak credentials.
     [supportsPromises] static void getWeakCredentials(
-        InsecureCredentialsCallback callback);
-
-    // Requests the plaintext password for |credential|. |callback| gets invoked
-    // with the same |credential|, whose |password| field will be set.
-    // |credential|: The insecure credential whose password is being retrieved.
-    // |reason|: The reason why the plaintext password is requested.
-    // |callback|: The callback that gets invoked with the result.
-    [supportsPromises] static void getPlaintextInsecurePassword(
-        InsecureCredential credential,
-        PlaintextReason reason,
-        GetPlaintextInsecurePasswordCallback callback);
-
-    // Requests to change the password of |credential| to |new_password|.
-    // Invokes |callback| or raises an error depending on whether the operation
-    // succeeded.
-    // |credential|: The credential whose password should be changed.
-    // |new_password|: The new password.
-    // |callback|: The callback that gets invoked in the end.
-    [supportsPromises] static void changeInsecureCredential(
-        InsecureCredential credential,
-        DOMString new_password,
-        optional VoidCallback callback);
-
-    // Requests to remove |credential| from the password store.
-    // Invokes |callback| on completion.
-    [supportsPromises] static void removeInsecureCredential(
-        InsecureCredential credential,
-        optional VoidCallback callback);
+        PasswordListCallback callback);
 
     // Requests to mute |credential| from the password store.
     // Invokes |callback| on completion.
     [supportsPromises] static void muteInsecureCredential(
-        InsecureCredential credential, optional VoidCallback callback);
+        PasswordUiEntry credential, optional VoidCallback callback);
 
     // Requests to unmute |credential| from the password store.
     // Invokes |callback| on completion.
     [supportsPromises] static void unmuteInsecureCredential(
-        InsecureCredential credential, optional VoidCallback callback);
+        PasswordUiEntry credential, optional VoidCallback callback);
 
     // Records that a change password flow was started for |credential|.
     // |credential|: The credential for which the flow was triggered.
     // |isAutomatedFlow|: Whether the flow is a manual one.
     // Invokes |callback| on completion.
     [supportsPromises] static void recordChangePasswordFlowStarted(
-        InsecureCredential credential,
+        PasswordUiEntry credential,
         boolean isManualFlow,
         optional VoidCallback callback);
 
@@ -458,7 +405,7 @@
     // on completion with a boolean parameter that signals whether the
     // credential was changed successfully.
     [supportsPromises] static void startAutomatedPasswordChange(
-        InsecureCredential credential,
+        PasswordUiEntry credential,
         optional StartAutomatedPasswordChangeCallback callback);
 
     // Requests whether the account store is a default location for saving
@@ -506,11 +453,11 @@
     // Fired when the compromised credentials changed.
     // |compromisedCredentials|: The updated compromised credentials.
     static void onCompromisedCredentialsChanged(
-        InsecureCredential[] compromisedCredentials);
+        PasswordUiEntry[] compromisedCredentials);
 
     // Fired when the weak credentials changed.
     // |weakCredentials|: The updated weak credentials.
-    static void onWeakCredentialsChanged(InsecureCredential[] weakCredentials);
+    static void onWeakCredentialsChanged(PasswordUiEntry[] weakCredentials);
 
     // Fired when the status of the password check changes.
     // |status|: The updated status of the password check.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6a37722c..c784a18 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -7332,11 +7332,11 @@
       "//chromeos/ash/components/dbus/update_engine",
       "//chromeos/ash/components/dbus/update_engine:proto",
       "//chromeos/ash/components/feature_usage",
+      "//chromeos/ash/components/string_matching",
       "//chromeos/ash/services/assistant/public/cpp",
       "//chromeos/components/onc",
       "//chromeos/components/quick_answers:quick_answers",
       "//chromeos/components/quick_answers/public/cpp:cpp",
-      "//chromeos/components/string_matching:string_matching",
       "//chromeos/components/sync_wifi",
       "//chromeos/constants",
       "//chromeos/dbus",
diff --git a/chrome/test/data/extensions/api_test/passwords_private/test.js b/chrome/test/data/extensions/api_test/passwords_private/test.js
index 0d7e672..e4ab2d7 100644
--- a/chrome/test/data/extensions/api_test/passwords_private/test.js
+++ b/chrome/test/data/extensions/api_test/passwords_private/test.js
@@ -362,195 +362,6 @@
     });
   },
 
-  function getPlaintextInsecurePassword() {
-    var compromisedCredential = {
-      id: 0,
-      urls: {
-        shown: 'example.com',
-        link: 'https://example.com',
-        signonRealm: 'https://example.com',
-      },
-      isAndroidCredential: false,
-      hasStartableScript: false,
-      username: 'alice',
-      compromisedInfo: {
-        compromiseTime: COMPROMISE_TIME,
-        elapsedTimeSinceCompromise: '3 days ago',
-        compromiseType: 'LEAKED',
-        isMuted: false,
-      },
-    };
-
-    chrome.passwordsPrivate.getPlaintextInsecurePassword(
-        compromisedCredential, chrome.passwordsPrivate.PlaintextReason.VIEW,
-        credentialWithPassword => {
-          chrome.test.assertEq('plaintext', credentialWithPassword.password);
-          chrome.test.succeed();
-        });
-  },
-
-  function getPlaintextInsecurePasswordFails() {
-    var compromisedCredential = {
-      id: 0,
-      urls: {
-        shown: 'example.com',
-        link: 'https://example.com',
-        signonRealm: 'https://example.com',
-      },
-      isAndroidCredential: false,
-      hasStartableScript: false,
-      username: 'alice',
-      compromisedInfo: {
-        compromiseTime: COMPROMISE_TIME,
-        elapsedTimeSinceCompromise: '3 days ago',
-        compromiseType: 'LEAKED',
-        isMuted: false,
-      },
-    };
-
-    chrome.passwordsPrivate.getPlaintextInsecurePassword(
-        compromisedCredential, chrome.passwordsPrivate.PlaintextReason.VIEW,
-        credentialWithPassword => {
-          chrome.test.assertLastError(
-              'Could not obtain plaintext insecure password. Either the user ' +
-              'is not authenticated or no matching password could be found.');
-          chrome.test.succeed();
-        });
-  },
-
-  function changeInsecureCredentialWithEmptyPasswordFails() {
-    chrome.passwordsPrivate.changeInsecureCredential(
-        {
-          id: 0,
-          urls: {
-            shown: 'example.com',
-            link: 'https://example.com',
-            signonRealm: 'https://example.com',
-          },
-          isAndroidCredential: false,
-          hasStartableScript: false,
-          username: 'alice',
-          compromisedInfo: {
-            compromiseTime: COMPROMISE_TIME,
-            elapsedTimeSinceCompromise: '3 days ago',
-            compromiseType: 'LEAKED',
-            isMuted: false,
-          },
-        },
-        '', () => {
-          chrome.test.assertLastError(
-              'Could not change the insecure credential. The new password ' +
-              'can\'t be empty.');
-          chrome.test.succeed();
-        });
-  },
-
-  function changeInsecureCredentialFails() {
-    chrome.passwordsPrivate.changeInsecureCredential(
-        {
-          id: 0,
-          isAndroidCredential: false,
-          hasStartableScript: false,
-          urls: {
-            shown: 'example.com',
-            link: 'https://example.com',
-            signonRealm: 'https://example.com',
-          },
-          username: 'alice',
-          compromisedInfo: {
-            compromiseTime: COMPROMISE_TIME,
-            elapsedTimeSinceCompromise: '3 days ago',
-            compromiseType: 'LEAKED',
-            isMuted: false,
-          },
-        },
-        'new_pass', () => {
-          chrome.test.assertLastError(
-              'Could not change the insecure credential. Either the user is ' +
-              'not authenticated or no matching password could be found.');
-          chrome.test.succeed();
-        });
-  },
-
-  function changeInsecureCredentialSucceeds() {
-    chrome.passwordsPrivate.changeInsecureCredential(
-        {
-          id: 0,
-          urls: {
-            shown: 'example.com',
-            link: 'https://example.com',
-            signonRealm: 'https://example.com',
-          },
-          isAndroidCredential: false,
-          hasStartableScript: false,
-          username: 'alice',
-          compromisedInfo: {
-            compromiseTime: COMPROMISE_TIME,
-            elapsedTimeSinceCompromise: '3 days ago',
-            compromiseType: 'LEAKED',
-            isMuted: false,
-          },
-        },
-        'new_pass', () => {
-          chrome.test.assertNoLastError();
-          chrome.test.succeed();
-        });
-  },
-
-  function removeInsecureCredentialFails() {
-    chrome.passwordsPrivate.removeInsecureCredential(
-        {
-          id: 0,
-          urls: {
-            shown: 'example.com',
-            link: 'https://example.com',
-            signonRealm: 'https://example.com',
-          },
-          isAndroidCredential: false,
-          hasStartableScript: false,
-          username: 'alice',
-          compromisedInfo: {
-            compromiseTime: COMPROMISE_TIME,
-            elapsedTimeSinceCompromise: '3 days ago',
-            compromiseType: 'LEAKED',
-            isMuted: false,
-          },
-        },
-        () => {
-          chrome.test.assertLastError(
-              'Could not remove the insecure credential. Probably no ' +
-              'matching password could be found.');
-          // Ensure that the callback is invoked.
-          chrome.test.succeed();
-        });
-  },
-
-  function removeInsecureCredentialSucceeds() {
-    chrome.passwordsPrivate.removeInsecureCredential(
-        {
-          id: 0,
-          urls: {
-            shown: 'example.com',
-            link: 'https://example.com',
-            signonRealm: 'https://example.com',
-          },
-          isAndroidCredential: false,
-          hasStartableScript: false,
-          username: 'alice',
-          compromisedInfo: {
-            compromiseTime: COMPROMISE_TIME,
-            elapsedTimeSinceCompromise: '3 days ago',
-            compromiseType: 'LEAKED',
-            isMuted: false,
-          },
-        },
-        () => {
-          chrome.test.assertNoLastError();
-          // Ensure that the callback is invoked.
-          chrome.test.succeed();
-        });
-  },
-
   function muteInsecureCredentialSucceeds() {
     chrome.passwordsPrivate.muteInsecureCredential(
         {
@@ -569,6 +380,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         () => {
           chrome.test.assertNoLastError();
@@ -595,6 +408,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         () => {
           chrome.test.assertLastError(
@@ -623,6 +438,8 @@
             compromiseType: 'LEAKED',
             isMuted: true,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         () => {
           chrome.test.assertNoLastError();
@@ -649,6 +466,8 @@
             compromiseType: 'LEAKED',
             isMuted: true,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         () => {
           chrome.test.assertLastError(
@@ -678,6 +497,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         true, () => {
           chrome.test.assertNoLastError();
@@ -704,6 +525,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         false, () => {
           chrome.test.assertNoLastError();
@@ -729,6 +552,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         true, () => {
           chrome.test.assertNoLastError();
@@ -793,6 +618,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         (status) => {
           chrome.test.assertNoLastError();
@@ -819,6 +646,8 @@
             compromiseType: 'LEAKED',
             isMuted: false,
           },
+          storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
+          note: '',
         },
         (status) => {
           chrome.test.assertNoLastError();
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
index d055d03b..a5ebd796 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_extension_test.js
@@ -17,15 +17,6 @@
   return element.classList.contains(ACTIVE_CATEGORY_BUTTON);
 }
 
-function categoryGroupSelector(category) {
-  return `emoji-group[category="${category}"]:not(.history)`;
-}
-
-function historyGroupSelector(category) {
-  return `[data-group="${category}-history"] > ` +
-         `emoji-group[category="${category}"]`;
-}
-
 suite('emoji-picker-extension', () => {
   /** @type {!EmojiPicker} */
   let emojiPicker;
@@ -33,8 +24,12 @@
   let findInEmojiPicker;
   /** @type {function(...!string): ?HTMLElement} */
   let findEmojiFirstButton;
-  /** @type {Array<string>} */
-  const categoryList = ['emoji', 'symbol', 'emoticon'];
+  /** @type {string} */
+  const emoticonGroupSelector =
+        'emoji-group[category="emoticon"]:not(.history)';
+  /** @type {string} */
+  const emoticonHistoryGroupSelector =
+        '[data-group="emoticon-history"] > emoji-group[category="emoticon"]';
 
   setup(() => {
     // Reset DOM state.
@@ -78,173 +73,31 @@
     });
   });
 
-  categoryList.forEach((category, categoryIndex) => {
-    test(category + ' category button is initialized correctly',
-      () => {
-        const categoryButton =
-            findInEmojiPicker('emoji-search').shadowRoot
-            .querySelectorAll('emoji-category-button')[categoryIndex]
-            .shadowRoot.querySelector('cr-icon-button');
-        if (categoryIndex === 0) {
-            assertTrue(
-                isCategoryButtonActive(categoryButton),
-                'First button must be active.');
-        } else {
-            assertFalse(
-                isCategoryButtonActive(categoryButton),
-                'All buttons must be inactive except the first one.');
-        }
-    });
-
-    test(category + ' category button should be active after clicking at it.',
-      () => {
-        const allCategoryButtons =
-            Array.from(findInEmojiPicker('emoji-search').shadowRoot
-                .querySelectorAll('emoji-category-button').values())
-                .map(item => item.shadowRoot.querySelector('cr-icon-button'));
-        const categoryButton = allCategoryButtons[categoryIndex];
-        categoryButton.click();
-        flush();
-        assertTrue(isCategoryButtonActive(categoryButton));
-        allCategoryButtons.forEach((categoryButtonItem, index) => {
-            if (index !== categoryIndex) {
-                assertFalse(isCategoryButtonActive(categoryButtonItem));
-            }
-        });
-      });
-
-    test('category group elements should be rendered.',
-      () => {
-        const numGroups = emojiPicker.categoriesData.filter(
-            item => item.category === category).length;
-        const numRenderedGroups = emojiPicker.shadowRoot
-            .querySelectorAll(categoryGroupSelector(category)).length;
-        assertGT(numGroups, 0);
-        assertEquals(numGroups, numRenderedGroups);
-      });
-
-    test(`each ${category} group should have the correct heading and correct` +
-         `number of ${category} entries.`,
-      () => {
-        const allGroups = emojiPicker.shadowRoot
-            .querySelectorAll(categoryGroupSelector(category));
-
-        const data = emojiPicker.categoriesData.filter(
-            item => item.category === category);
-        const groupElements =
-            emojiPicker.categoriesGroupElements.filter(
-                item => item.category === category);
-
-        // The first group element is 'Recently used'.
-        assertEquals(groupElements[0].name, 'Recently used');
-
-        // Emoticon group elements are created for all data + history.
-        assertEquals(groupElements.length, data.length + 1);
-
-        for (let idx = 0; idx < allGroups.length; ++idx) {
-            const group = allGroups[idx];
-            const actualFirstGroupName = (/** @type {string} */ (
-                group.shadowRoot.querySelector('#heading-left')
-                .innerHTML.trim())).replace('&amp;', '&');
-            const expectedFirstGroupName = groupElements[idx+1].name;
-            assertEquals(expectedFirstGroupName, actualFirstGroupName);
-            assertEquals(groupElements[idx+1].emoji.length,
-                group.shadowRoot.querySelectorAll('.emoji-button').length);
-        }
-      });
-
-    test(`clicking at a ${category} button should trigger the clicking event` +
-         `correct ${category} string and name.`,
-      async () => {
-        const firstButton = await waitForCondition(
-            () => findEmojiFirstButton(categoryGroupSelector(category)));
-        const groupElements =
-            emojiPicker.categoriesGroupElements.filter(
-                item => item.category === category && !item.isHistory);
-        const expectedString = groupElements[0].emoji[0].base.string;
-        const expectedName = groupElements[0].emoji[0].base.name;
-        const buttonClickPromise = new Promise(
-            (resolve) =>
-                emojiPicker.addEventListener(EMOJI_BUTTON_CLICK, (event) => {
-                assertEquals(expectedString, event.detail.text);
-                assertEquals(expectedName, event.detail.name);
-                resolve();
-                }));
-        firstButton.click();
-        await flush();
-        await waitWithTimeout(
-            buttonClickPromise, 1000,
-            `Failed to receive ${category} button click event`);
-      });
-
-    test(`recently used ${category} group should be hidden when empty.`,
-      () => {
-        assertEquals(findInEmojiPicker(historyGroupSelector(
-            category)).style.display, '');
-      });
-
-    test(`history tab button must be disabled when the ${category} history` +
-         ' is empty.',
-      () => {
-        // It is assumed that the order of categoryList is the same as buttons.
-        const categoryButton =
-            findInEmojiPicker('emoji-search').shadowRoot
-            .querySelectorAll('emoji-category-button')[categoryIndex]
-            .shadowRoot.querySelector('cr-icon-button');
-        categoryButton.click();
-        flush();
-        const historyTab = findInEmojiPicker(
-            `#tabs emoji-group-button[data-group="${category}-history"]`,
-            'cr-icon-button');
-        assertTrue(historyTab.disabled);
-      });
-
-    test(`clicking at recently used ${category} buttons should trigger ` +
-         `${category} insertion.`,
-      async () => {
-        emojiPicker.updateIncognitoState(false);
-
-        const emojiButton = findEmojiFirstButton(
-          categoryGroupSelector(category));
-          emojiButton.click();
-
-        const recentlyUsedButton = await waitForCondition(
-            () => findEmojiFirstButton(historyGroupSelector(category)));
-        const buttonClickPromise = new Promise(
-            (resolve) =>
-                emojiPicker.addEventListener(EMOJI_BUTTON_CLICK, (event) => {
-                  assertEquals(
-                      emojiButton.innerHTML.trim(), event.detail.text);
-                  resolve();
-                }));
-
-        recentlyUsedButton.click();
-        await waitWithTimeout(
-            buttonClickPromise, 1000,
-            `Clicking at recently used ${category} buttons does not ` +
-            `trigger ${category} insertion.`);
-      });
-
-    test(`recently used ${category} group should contain the ` +
-         `correct ${category}  after it is clicked.`,
-      async () => {
-        emojiPicker.updateIncognitoState(false);
-
-        const emojiButton = findEmojiFirstButton(
-            categoryGroupSelector(category));
-        emojiButton.click();
-
-        const recentEmojiButton = await waitForCondition(
-            () => findEmojiFirstButton(historyGroupSelector(category)));
-        assert(recentEmojiButton);
-
-        const recentlyUsedEmoji =
-            findInEmojiPicker(historyGroupSelector(category))
-            .shadowRoot.querySelectorAll('.emoji-button');
-        assertEquals(1, recentlyUsedEmoji.length);
-      });
+  test('emoji category button should be active by default.', () => {
+    const emojiCategoryButton = findInEmojiPicker(
+        'emoji-search', 'emoji-category-button', 'cr-icon-button');
+    assertTrue(isCategoryButtonActive(emojiCategoryButton));
   });
 
+  test('emoticon category button should be inactive by default.', () => {
+    const emoticonCategoryButton = findInEmojiPicker(
+        'emoji-search', 'emoji-category-button:last-of-type', 'cr-icon-button');
+    assertFalse(isCategoryButtonActive(emoticonCategoryButton));
+  });
+
+  test(
+      'emoticon category button should be active after clicking at it.', () => {
+        const emojiCategoryButton = findInEmojiPicker(
+            'emoji-search', 'emoji-category-button', 'cr-icon-button');
+        const emoticonCategoryButton = findInEmojiPicker(
+            'emoji-search', 'emoji-category-button:last-of-type',
+            'cr-icon-button');
+        emoticonCategoryButton.click();
+        flush();
+        assertTrue(isCategoryButtonActive(emoticonCategoryButton));
+        assertFalse(isCategoryButtonActive(emojiCategoryButton));
+      });
+
   test(
       `the first tab of the next pagination should be active when clicking at
         either chevron.`,
@@ -272,6 +125,140 @@
                 isGroupButtonActive(firstEmoticonTabInFirstPage));
       });
 
+  test('all emoticon groups should be rendered.', () => {
+    const numEmoticons = emojiPicker.categoriesData.filter(
+        item => item.category === 'emoticon').length;
+    assertGT(numEmoticons, 0);
+    assertEquals(
+        numEmoticons,
+        emojiPicker.shadowRoot.querySelectorAll(
+            emoticonGroupSelector).length);
+  });
+
+  test(
+      'each emoticon group should have the correct heading and correct' +
+          'number of emoticon entries.',
+      async () => {
+        const allEmoticonGroups =
+            emojiPicker.shadowRoot.querySelectorAll(emoticonGroupSelector);
+
+        const emoticonData = emojiPicker.categoriesData.filter(
+            item => item.category === 'emoticon');
+        const emoticonGroupElements =
+            emojiPicker.categoriesGroupElements.filter(
+                item => item.category === 'emoticon');
+
+        // The first group element is 'Recently used'.
+        assertEquals(emoticonGroupElements[0].name, 'Recently used');
+
+        // Emoticon group elements are created for all data + history.
+        assertEquals(emoticonGroupElements.length, emoticonData.length + 1);
+
+        for (let idx = 0; idx < allEmoticonGroups.length; ++idx) {
+          const group = allEmoticonGroups[idx];
+          const actualFirstGroupName =
+              group.shadowRoot.querySelector('#heading-left').innerHTML.trim();
+          const expectedFirstGroupName = emoticonGroupElements[idx+1].name;
+          assertEquals(expectedFirstGroupName, actualFirstGroupName);
+
+          const expectedNumberOfEmoticons =
+            emoticonGroupElements[idx+1].emoji.length;
+          await waitForCondition(
+              () => expectedNumberOfEmoticons ===
+                  group.shadowRoot.querySelectorAll('.emoji-button').length);
+        }
+      });
+
+  test(
+      'clicking at an emoticon button should trigger the clicking event with ' +
+          'correct emoticon string and name.',
+      async () => {
+        const firstEmoticonButton = await waitForCondition(
+            () => findEmojiFirstButton(emoticonGroupSelector));
+        const emoticonGroupElements =
+            emojiPicker.categoriesGroupElements.filter(
+                item => item.category === 'emoticon' && !item.isHistory);
+        const expectedEmoticonString =
+            emoticonGroupElements[0].emoji[0].base.string;
+        const expectedEmoticonName =
+            emoticonGroupElements[0].emoji[0].base.name;
+        const buttonClickPromise = new Promise(
+            (resolve) =>
+                emojiPicker.addEventListener(EMOJI_BUTTON_CLICK, (event) => {
+                  assertEquals(expectedEmoticonString, event.detail.text);
+                  assertEquals(expectedEmoticonName, event.detail.name);
+                  resolve();
+                }));
+        firstEmoticonButton.click();
+        await flush();
+        await waitWithTimeout(
+            buttonClickPromise, 1000,
+            'Failed to receive emoticon button click event');
+      });
+
+  test('there should be no recently used emoticon group when empty.', () => {
+    assert(!findInEmojiPicker('[data-group=emoticon-history] emoticon-group'));
+  });
+
+  test(
+      'history tab button must be disabled when the emoticon history is empty.',
+      () => {
+        const emoticonCategoryButton = findInEmojiPicker(
+            'emoji-search', 'emoji-category-button:last-of-type',
+            'cr-icon-button');
+        emoticonCategoryButton.click();
+        flush();
+        const emoticonHistoryTab = findInEmojiPicker(
+            '.pagination [data-group=emoticon-history]', 'cr-icon-button');
+        assertTrue(emoticonHistoryTab.disabled);
+      });
+
+  test(
+      'clicking at recently used emoticon buttons should trigger emoticon ' +
+          'insertion.',
+      async () => {
+        emojiPicker.updateIncognitoState(false);
+
+        const emoticonButton = findEmojiFirstButton(emoticonGroupSelector);
+        emoticonButton.click();
+
+        const recentlyUsedEmoticonButton = await waitForCondition(
+            () => findEmojiFirstButton(emoticonHistoryGroupSelector));
+        const buttonClickPromise = new Promise(
+            (resolve) =>
+                emojiPicker.addEventListener(EMOJI_BUTTON_CLICK, (event) => {
+                  assertEquals(
+                      emoticonButton.innerHTML.trim(), event.detail.text);
+                  resolve();
+                }));
+
+        recentlyUsedEmoticonButton.click();
+        await waitWithTimeout(
+            buttonClickPromise, 1000,
+            'Clicking at recently used emoticon buttons does not trigger ' +
+                'emoticon insertion.');
+      });
+
+  test(
+      'recently used emoticon group should contain the correct emoticon ' +
+          'after it is clicked.',
+      async () => {
+        emojiPicker.updateIncognitoState(false);
+        const emoticonButton = findEmojiFirstButton(emoticonGroupSelector);
+        emoticonButton.click();
+
+        const recentEmoticonButton = await waitForCondition(
+            () => findEmojiFirstButton(emoticonHistoryGroupSelector));
+        assert(recentEmoticonButton);
+
+        const recentlyUsedEmoticons =
+            findInEmojiPicker(
+                emoticonHistoryGroupSelector,
+                )
+                .shadowRoot.querySelectorAll('.emoji-button');
+        assertEquals(1, recentlyUsedEmoticons.length);
+      });
+
   test(
       'Scrolling to an emoticon group should activate the emoticon category ' +
           'button.',
@@ -289,7 +276,6 @@
             () => isCategoryButtonActive(emoticonCategoryButton) &&
                 !isCategoryButtonActive(emojiCategoryButton));
       });
-
   test(
       'Scrolling to an emoticon group should activate the corresponding ' +
           'subcategory tab.',
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
index 74284ae..528542e 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.js
@@ -67,9 +67,8 @@
       () => {
         emojiSearch.search = 'face';
         flush();
-        const emojiResults =
-            findInEmojiPicker('emoji-search', 'emoji-group[category="emoji"]')
-            .shadowRoot.querySelectorAll('.emoji-button');
+        const emojiResults = findInEmojiPicker('emoji-search', 'emoji-group')
+                                 .shadowRoot.querySelectorAll('.emoji-button');
         assertGT(emojiResults.length, 0);
         const emoticonResults =
           findInEmojiPicker(
diff --git a/chrome/test/data/webui/settings/password_check_test.ts b/chrome/test/data/webui/settings/password_check_test.ts
index c24eebc..62fba6cb 100644
--- a/chrome/test/data/webui/settings/password_check_test.ts
+++ b/chrome/test/data/webui/settings/password_check_test.ts
@@ -39,7 +39,7 @@
 }
 
 function createEditDialog(
-    leakedCredential: chrome.passwordsPrivate.InsecureCredential):
+    leakedCredential: chrome.passwordsPrivate.PasswordUiEntry):
     SettingsPasswordCheckEditDialogElement {
   const editDialog =
       document.createElement('settings-password-check-edit-dialog');
@@ -53,7 +53,7 @@
  * Helper method used to create a compromised list item.
  */
 function createLeakedPasswordItem(
-    entry: chrome.passwordsPrivate.InsecureCredential,
+    entry: chrome.passwordsPrivate.PasswordUiEntry,
     mutingEnabled = false): PasswordCheckListItemElement {
   const leakedPasswordItem = document.createElement('password-check-list-item');
   leakedPasswordItem.item = entry;
@@ -112,7 +112,7 @@
  * Helper method used to create a remove password confirmation dialog.
  */
 function createRemovePasswordDialog(
-    entry: chrome.passwordsPrivate.InsecureCredential):
+    entry: chrome.passwordsPrivate.PasswordUiEntry):
     SettingsPasswordRemoveConfirmationDialogElement {
   const element =
       document.createElement('settings-password-remove-confirmation-dialog');
@@ -180,7 +180,7 @@
  */
 function validateInsecurePasswordsList(
     checkPasswordSection: SettingsPasswordCheckElement,
-    insecureCredentials: chrome.passwordsPrivate.InsecureCredential[],
+    insecureCredentials: chrome.passwordsPrivate.PasswordUiEntry[],
     isCompromised: boolean, isMuted: boolean = false) {
   const listElements =
       getElementsByType(checkPasswordSection, isCompromised, isMuted);
@@ -220,7 +220,7 @@
  */
 function validateLeakedPasswordsList(
     checkPasswordSection: SettingsPasswordCheckElement,
-    compromisedCredentials: chrome.passwordsPrivate.InsecureCredential[],
+    compromisedCredentials: chrome.passwordsPrivate.PasswordUiEntry[],
     isMuted = false) {
   validateInsecurePasswordsList(
       checkPasswordSection, compromisedCredentials, /*isCompromised*/ true,
@@ -800,13 +800,12 @@
     removeDialog.$.remove.click();
     const interaction =
         await passwordManager.whenCalled('recordPasswordCheckInteraction');
-    const {id, username, formattedOrigin} =
-        await passwordManager.whenCalled('removeInsecureCredential');
+    const {id, fromStores} =
+        await passwordManager.whenCalled('removeSavedPassword');
 
     assertEquals(PasswordCheckInteraction.REMOVE_PASSWORD, interaction);
     assertEquals(0, id);
-    assertEquals('test4', username);
-    assertEquals('one.com', formattedOrigin);
+    assertEquals(entry.storedIn, fromStores);
   });
 
   // Test verifies that clicking dismiss button is calling proper proxy
@@ -1844,7 +1843,7 @@
     checkPasswordSection.$.menuEditPassword.click();
     // Since we did not specify a plaintext password above, this request
     // should fail.
-    await passwordManager.whenCalled('getPlaintextInsecurePassword');
+    await passwordManager.whenCalled('requestPlaintextPassword');
     // Verify that the edit dialog has not become visible.
     await flushTasks();
     assertFalse(isElementVisible(checkPasswordSection.shadowRoot!.querySelector(
@@ -1872,10 +1871,10 @@
     // Open the more actions menu and click 'Edit Password'.
     node.$.more.click();
     checkPasswordSection.$.menuEditPassword.click();
-    const {credential, reason} =
-        await passwordManager.whenCalled('getPlaintextInsecurePassword');
+    const {id, reason} =
+        await passwordManager.whenCalled('requestPlaintextPassword');
     await flushTasks();
-    assertEquals(passwordManager.data.leakedCredentials[0], credential);
+    assertEquals(passwordManager.data.leakedCredentials[0]!.id, id);
     assertEquals(chrome.passwordsPrivate.PlaintextReason.EDIT, reason);
 
     // Verify that the edit dialog has become visible.
@@ -1904,14 +1903,17 @@
     editDialog.$.passwordInput.value = 'yadhtribym';
     assertFalse(editDialog.$.passwordInput.invalid);
     assertFalse(editDialog.$.save.disabled);
+    passwordManager.setChangeSavedPasswordResponse(1);
     editDialog.$.save.click();
 
     const interaction =
         await passwordManager.whenCalled('recordPasswordCheckInteraction');
-    const {newPassword} =
-        await passwordManager.whenCalled('changeInsecureCredential');
+    const {id, params} =
+        await passwordManager.whenCalled('changeSavedPassword');
+
     assertEquals(PasswordCheckInteraction.EDIT_PASSWORD, interaction);
-    assertEquals('yadhtribym', newPassword);
+    assertEquals(leakedPassword.id, id);
+    assertEquals('yadhtribym', params.password);
   });
 
   test('editDialogCancel', function() {
@@ -1925,7 +1927,7 @@
     editDialog.$.passwordInput.value = 'yadhtribym';
     editDialog.$.cancel.click();
 
-    assertEquals(0, passwordManager.getCallCount('changeInsecureCredential'));
+    assertEquals(0, passwordManager.getCallCount('changeSavedPassword'));
   });
 
   test('startEqualsTrueSearchParameterStartsCheck', async function() {
@@ -1965,7 +1967,7 @@
 
     assertEquals(PasswordCheckInteraction.SHOW_PASSWORD, interaction);
     const {reason} =
-        await passwordManager.whenCalled('getPlaintextInsecurePassword');
+        await passwordManager.whenCalled('requestPlaintextPassword');
     await flushTasks();
     assertEquals(chrome.passwordsPrivate.PlaintextReason.VIEW, reason);
     assertEquals('text', node.$.insecurePassword.type);
@@ -1996,7 +1998,7 @@
     // Open the more actions menu and click 'Show Password'.
     node.$.more.click();
     checkPasswordSection.$.menuShowPassword.click();
-    await passwordManager.whenCalled('getPlaintextInsecurePassword');
+    await passwordManager.whenCalled('requestPlaintextPassword');
     await flushTasks();
     // Verify that password field didn't change
     assertEquals('password', node.$.insecurePassword.type);
@@ -2051,7 +2053,7 @@
     assertTrue(isElementVisible(editDisclaimerDialog));
     editDisclaimerDialog.$.edit.click();
 
-    await passwordManager.whenCalled('getPlaintextInsecurePassword');
+    await passwordManager.whenCalled('requestPlaintextPassword');
     flush();
     assertTrue(isElementVisible(editDisclaimerDialog));
   });
@@ -2081,7 +2083,7 @@
 
     passwordManager.setPlaintextPassword('test4');
     node.tokenRequestManager.resolve();
-    await passwordManager.whenCalled('getPlaintextInsecurePassword');
+    await passwordManager.whenCalled('requestPlaintextPassword');
     await flushTasks();
     assertEquals('text', node.$.insecurePassword.type);
     assertEquals('test4', node.$.insecurePassword.value);
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
index a36370c..a9ac630 100644
--- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
+++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
@@ -62,6 +62,7 @@
     isAndroidCredential: params.isAndroidCredential || false,
     note: note,
     password: '',
+    hasStartableScript: false,
   };
 }
 
@@ -171,9 +172,10 @@
  */
 export function makeInsecureCredential(
     url: string, username: string,
-    id?: number): chrome.passwordsPrivate.InsecureCredential {
+    id?: number): chrome.passwordsPrivate.PasswordUiEntry {
   return {
     id: id || 0,
+    storedIn: chrome.passwordsPrivate.PasswordStoreSet.DEVICE,
     changePasswordUrl: `http://${url}/`,
     hasStartableScript: false,
     urls: {
@@ -182,6 +184,7 @@
       link: `http://${url}/`,
     },
     username: username,
+    note: '',
     isAndroidCredential: false,
   };
 }
@@ -192,7 +195,7 @@
 export function makeCompromisedCredential(
     url: string, username: string, type: chrome.passwordsPrivate.CompromiseType,
     id?: number, elapsedMinSinceCompromise?: number,
-    isMuted?: boolean): chrome.passwordsPrivate.InsecureCredential {
+    isMuted?: boolean): chrome.passwordsPrivate.PasswordUiEntry {
   const credential = makeInsecureCredential(url, username, id);
   elapsedMinSinceCompromise = elapsedMinSinceCompromise || 0;
   credential.compromisedInfo = {
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.ts b/chrome/test/data/webui/settings/test_password_manager_proxy.ts
index 0d85a83..4691221 100644
--- a/chrome/test/data/webui/settings/test_password_manager_proxy.ts
+++ b/chrome/test/data/webui/settings/test_password_manager_proxy.ts
@@ -63,8 +63,8 @@
   data: {
     passwords: chrome.passwordsPrivate.PasswordUiEntry[],
     exceptions: chrome.passwordsPrivate.ExceptionEntry[],
-    leakedCredentials: chrome.passwordsPrivate.InsecureCredential[],
-    weakCredentials: chrome.passwordsPrivate.InsecureCredential[],
+    leakedCredentials: chrome.passwordsPrivate.PasswordUiEntry[],
+    weakCredentials: chrome.passwordsPrivate.PasswordUiEntry[],
     checkStatus: chrome.passwordsPrivate.PasswordCheckStatus,
   };
 
@@ -97,12 +97,10 @@
     super([
       'addPassword',
       'cancelExportPasswords',
-      'changeInsecureCredential',
       'changeSavedPassword',
       'exportPasswords',
       'getCompromisedCredentials',
       'getPasswordCheckStatus',
-      'getPlaintextInsecurePassword',
       'getUrlCollection',
       'getWeakCredentials',
       'importPasswords',
@@ -115,7 +113,6 @@
       'recordPasswordCheckReferrer',
       'refreshScriptsIfNecessary',
       'removeException',
-      'removeInsecureCredential',
       'removeSavedPassword',
       'requestExportProgressStatus',
       'requestPlaintextPassword',
@@ -297,7 +294,7 @@
   }
 
   startAutomatedPasswordChange(credential:
-                                   chrome.passwordsPrivate.InsecureCredential) {
+                                   chrome.passwordsPrivate.PasswordUiEntry) {
     this.methodCalled('startAutomatedPasswordChange', credential);
     // Return `false` for empty origins for testing purposes.
     return Promise.resolve(!!credential.changePasswordUrl);
@@ -322,33 +319,6 @@
   removePasswordCheckStatusListener(_listener:
                                         PasswordCheckStatusChangedListener) {}
 
-  getPlaintextInsecurePassword(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      reason: chrome.passwordsPrivate.PlaintextReason) {
-    this.methodCalled('getPlaintextInsecurePassword', {credential, reason});
-    if (!this.plaintextPassword_) {
-      return Promise.reject(new Error('Could not obtain plaintext password'));
-    }
-
-    const newCredential =
-        /** @type {chrome.passwordsPrivate.InsecureCredential} */ (
-            Object.assign({}, credential));
-    newCredential.password = this.plaintextPassword_;
-    return Promise.resolve(newCredential);
-  }
-
-  changeInsecureCredential(
-      credential: chrome.passwordsPrivate.InsecureCredential,
-      newPassword: string) {
-    this.methodCalled('changeInsecureCredential', {credential, newPassword});
-    return Promise.resolve();
-  }
-
-  removeInsecureCredential(insecureCredential:
-                               chrome.passwordsPrivate.InsecureCredential) {
-    this.methodCalled('removeInsecureCredential', insecureCredential);
-  }
-
   recordPasswordCheckInteraction(interaction: PasswordCheckInteraction) {
     this.methodCalled('recordPasswordCheckInteraction', interaction);
   }
@@ -407,17 +377,17 @@
   }
 
   muteInsecureCredential(insecureCredential:
-                             chrome.passwordsPrivate.InsecureCredential) {
+                             chrome.passwordsPrivate.PasswordUiEntry) {
     this.methodCalled('muteInsecureCredential', insecureCredential);
   }
 
   unmuteInsecureCredential(insecureCredential:
-                               chrome.passwordsPrivate.InsecureCredential) {
+                               chrome.passwordsPrivate.PasswordUiEntry) {
     this.methodCalled('unmuteInsecureCredential', insecureCredential);
   }
 
   recordChangePasswordFlowStarted(
-      insecureCredential: chrome.passwordsPrivate.InsecureCredential,
+      insecureCredential: chrome.passwordsPrivate.PasswordUiEntry,
       isManualFlow: boolean) {
     this.methodCalled(
         'recordChangePasswordFlowStarted', insecureCredential, isManualFlow);
diff --git a/chromeos/ash/components/BUILD.gn b/chromeos/ash/components/BUILD.gn
index dc1bdb82..39fb602 100644
--- a/chromeos/ash/components/BUILD.gn
+++ b/chromeos/ash/components/BUILD.gn
@@ -20,6 +20,7 @@
     "//chromeos/ash/components/memory:unit_tests",
     "//chromeos/ash/components/network:unit_tests",
     "//chromeos/ash/components/oobe_quick_start:unit_tests",
+    "//chromeos/ash/components/string_matching:unit_tests",
     "//chromeos/ash/components/trash_service:unit_tests",
   ]
 
diff --git a/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.cc b/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.cc
index c1c2ba0..75473ae 100644
--- a/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.cc
+++ b/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.cc
@@ -35,4 +35,17 @@
 
 void FakePatchPanelClient::GetDevices(GetDevicesCallback callback) {}
 
+void FakePatchPanelClient::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void FakePatchPanelClient::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+void FakePatchPanelClient::NotifyNetworkConfigurationChanged() {
+  for (auto& observer : observer_list_)
+    observer.NetworkConfigurationChanged();
+}
+
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.h b/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.h
index 5fecb5c..8b17d3f 100644
--- a/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.h
+++ b/chromeos/ash/components/dbus/patchpanel/fake_patchpanel_client.h
@@ -7,6 +7,8 @@
 
 #include "chromeos/ash/components/dbus/patchpanel/patchpanel_client.h"
 
+#include "base/observer_list.h"
+
 namespace ash {
 
 // FakePatchPanelClient is a stub implementation of PatchPanelClient used for
@@ -22,6 +24,8 @@
 
   // PatchPanelClient:
   void GetDevices(GetDevicesCallback callback) override;
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
 
  protected:
   friend class PatchPanelClient;
@@ -30,6 +34,12 @@
   ~FakePatchPanelClient() override;
 
   void Init(dbus::Bus* bus) override {}
+
+  // Calls NetworkConfigurationChanged() on Observer instances.
+  void NotifyNetworkConfigurationChanged();
+
+  // List of observers.
+  base::ObserverList<Observer> observer_list_;
 };
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/patchpanel/patchpanel_client.cc b/chromeos/ash/components/dbus/patchpanel/patchpanel_client.cc
index 6403936..0380378 100644
--- a/chromeos/ash/components/dbus/patchpanel/patchpanel_client.cc
+++ b/chromeos/ash/components/dbus/patchpanel/patchpanel_client.cc
@@ -22,6 +22,14 @@
 
 PatchPanelClient* g_instance = nullptr;
 
+void OnSignalConnected(const std::string& interface_name,
+                       const std::string& signal_name,
+                       bool success) {
+  DCHECK_EQ(interface_name, patchpanel::kPatchPanelInterface);
+  LOG_IF(DFATAL, !success) << "Failed to connect to D-Bus signal; interface: "
+                           << interface_name << "; signal: " << signal_name;
+}
+
 // "Real" implementation of PatchPanelClient talking to the PatchPanel daemon
 // on the Chrome OS side.
 class PatchPanelClientImpl : public PatchPanelClient {
@@ -53,6 +61,15 @@
     patchpanel_proxy_ = bus->GetObjectProxy(
         patchpanel::kPatchPanelServiceName,
         dbus::ObjectPath(patchpanel::kPatchPanelServicePath));
+    ConnectToSignals();
+  }
+
+  void AddObserver(Observer* observer) override {
+    observer_list_.AddObserver(observer);
+  }
+
+  void RemoveObserver(Observer* observer) override {
+    observer_list_.RemoveObserver(observer);
   }
 
  private:
@@ -70,9 +87,29 @@
         std::make_move_iterator(response.devices().end())));
   }
 
+  void OnNetworkConfigurationChanged(dbus::Signal* signal) {
+    for (auto& observer : observer_list_) {
+      observer.NetworkConfigurationChanged();
+    }
+  }
+
+  // Connects the dbus signals.
+  void ConnectToSignals() {
+    patchpanel_proxy_->ConnectToSignal(
+        patchpanel::kPatchPanelInterface,
+        patchpanel::kNetworkConfigurationChangedSignal,
+        base::BindRepeating(
+            &PatchPanelClientImpl::OnNetworkConfigurationChanged,
+            weak_factory_.GetWeakPtr()),
+        base::BindOnce(&OnSignalConnected));
+  }
+
   // D-Bus proxy for the PatchPanel daemon, not owned.
   dbus::ObjectProxy* patchpanel_proxy_ = nullptr;
 
+  // List of observers for dbus signals.
+  base::ObserverList<Observer> observer_list_;
+
   base::WeakPtrFactory<PatchPanelClientImpl> weak_factory_{this};
 };
 
diff --git a/chromeos/ash/components/dbus/patchpanel/patchpanel_client.h b/chromeos/ash/components/dbus/patchpanel/patchpanel_client.h
index dd56d57..a086add 100644
--- a/chromeos/ash/components/dbus/patchpanel/patchpanel_client.h
+++ b/chromeos/ash/components/dbus/patchpanel/patchpanel_client.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/component_export.h"
+#include "base/observer_list_types.h"
 #include "chromeos/ash/components/dbus/patchpanel/patchpanel_service.pb.h"
 #include "chromeos/dbus/common/dbus_client.h"
 #include "dbus/object_proxy.h"
@@ -18,6 +19,13 @@
 // third_party/cros_system_api/dbus/patchpanel.
 class COMPONENT_EXPORT(PATCHPANEL) PatchPanelClient : public DBusClient {
  public:
+  class Observer : public base::CheckedObserver {
+   public:
+    // Called when NetworkConfigurationChanged signal is received, when the
+    // there is a network configuration change.
+    virtual void NetworkConfigurationChanged() {}
+  };
+
   using GetDevicesCallback = base::OnceCallback<void(
       const std::vector<patchpanel::NetworkDevice>& devices)>;
 
@@ -40,6 +48,12 @@
   // patchpanel.
   virtual void GetDevices(GetDevicesCallback callback) = 0;
 
+  // Adds an observer.
+  virtual void AddObserver(Observer* observer) = 0;
+
+  // Removes an observer if added.
+  virtual void RemoveObserver(Observer* observer) = 0;
+
  protected:
   // Initialize/Shutdown should be used instead.
   PatchPanelClient();
diff --git a/chromeos/ash/components/local_search_service/BUILD.gn b/chromeos/ash/components/local_search_service/BUILD.gn
index aba48fef..7cd96b6 100644
--- a/chromeos/ash/components/local_search_service/BUILD.gn
+++ b/chromeos/ash/components/local_search_service/BUILD.gn
@@ -34,7 +34,7 @@
     "//base:i18n",
     "//cc",
     "//chromeos/ash/components/local_search_service/public/mojom",
-    "//chromeos/components/string_matching",
+    "//chromeos/ash/components/string_matching",
   ]
 
   public_deps = [
diff --git a/chromeos/ash/components/local_search_service/DEPS b/chromeos/ash/components/local_search_service/DEPS
index 33586110..6d002db 100644
--- a/chromeos/ash/components/local_search_service/DEPS
+++ b/chromeos/ash/components/local_search_service/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+chromeos/ash/components/string_matching",
   "+components/keyed_service/content",
   "+components/keyed_service/core",
   "+components/metrics",
diff --git a/chromeos/ash/components/local_search_service/content_extraction_utils.cc b/chromeos/ash/components/local_search_service/content_extraction_utils.cc
index 2eba372..6d3c853 100644
--- a/chromeos/ash/components/local_search_service/content_extraction_utils.cc
+++ b/chromeos/ash/components/local_search_service/content_extraction_utils.cc
@@ -16,14 +16,15 @@
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/icu/source/i18n/unicode/translit.h"
 
 namespace chromeos {
 namespace local_search_service {
 
 namespace {
-using chromeos::string_matching::TokenizedString;
+
+using ::ash::string_matching::TokenizedString;
 
 std::unique_ptr<icu::Transliterator> CreateDiacriticRemover() {
   UErrorCode status = U_ZERO_ERROR;
diff --git a/chromeos/ash/components/local_search_service/inverted_index_search.cc b/chromeos/ash/components/local_search_service/inverted_index_search.cc
index 934876b..48581a2 100644
--- a/chromeos/ash/components/local_search_service/inverted_index_search.cc
+++ b/chromeos/ash/components/local_search_service/inverted_index_search.cc
@@ -19,7 +19,7 @@
 #include "base/time/time.h"
 #include "chromeos/ash/components/local_search_service/content_extraction_utils.h"
 #include "chromeos/ash/components/local_search_service/inverted_index.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
@@ -27,7 +27,7 @@
 
 namespace {
 
-using chromeos::string_matching::TokenizedString;
+using ::ash::string_matching::TokenizedString;
 using ExtractedContent =
     std::vector<std::pair<std::string, std::vector<Token>>>;
 
diff --git a/chromeos/ash/components/local_search_service/linear_map_search.cc b/chromeos/ash/components/local_search_service/linear_map_search.cc
index 1153aae..bb409ee 100644
--- a/chromeos/ash/components/local_search_service/linear_map_search.cc
+++ b/chromeos/ash/components/local_search_service/linear_map_search.cc
@@ -11,8 +11,8 @@
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/local_search_service/search_utils.h"
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
@@ -20,9 +20,8 @@
 
 namespace {
 
-using chromeos::string_matching::FuzzyTokenizedStringMatch;
-using chromeos::string_matching::TokenizedString;
-
+using ::ash::string_matching::FuzzyTokenizedStringMatch;
+using ::ash::string_matching::TokenizedString;
 using Positions = std::vector<local_search_service::Position>;
 using TokenizedStringWithId =
     std::pair<std::string, std::unique_ptr<TokenizedString>>;
diff --git a/chromeos/ash/components/local_search_service/linear_map_search.h b/chromeos/ash/components/local_search_service/linear_map_search.h
index 3635ce1..63fabf0 100644
--- a/chromeos/ash/components/local_search_service/linear_map_search.h
+++ b/chromeos/ash/components/local_search_service/linear_map_search.h
@@ -13,20 +13,18 @@
 #include "chromeos/ash/components/local_search_service/index.h"
 #include "chromeos/ash/components/local_search_service/shared_structs.h"
 
-namespace chromeos {
-
-namespace string_matching {
+namespace ash::string_matching {
 class TokenizedString;
-}  // namespace string_matching
+}
 
+namespace chromeos {
 namespace local_search_service {
 
 // A map from key to a vector of (tag-id, tokenized tag).
-typedef std::map<
-    std::string,
-    std::vector<
-        std::pair<std::string,
-                  std::unique_ptr<chromeos::string_matching::TokenizedString>>>>
+typedef std::map<std::string,
+                 std::vector<std::pair<
+                     std::string,
+                     std::unique_ptr<ash::string_matching::TokenizedString>>>>
     KeyToTagVector;
 
 // An implementation of Index.
diff --git a/chromeos/ash/components/local_search_service/search_utils.cc b/chromeos/ash/components/local_search_service/search_utils.cc
index 3740086..60fb092 100644
--- a/chromeos/ash/components/local_search_service/search_utils.cc
+++ b/chromeos/ash/components/local_search_service/search_utils.cc
@@ -17,13 +17,16 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/ash/components/local_search_service/shared_structs.h"
-#include "chromeos/components/string_matching/sequence_matcher.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/sequence_matcher.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/icu/source/i18n/unicode/translit.h"
 
 namespace chromeos {
 namespace local_search_service {
 
+// TODO(https://crbug.com/1164001): remove after migrating to namespace ash.
+namespace string_matching = ::ash::string_matching;
+
 float ExactPrefixMatchScore(const std::u16string& query,
                             const std::u16string& text) {
   const size_t query_len = query.size();
@@ -41,9 +44,9 @@
 }
 
 float BlockMatchScore(const std::u16string& query, const std::u16string& text) {
-  return chromeos::string_matching::SequenceMatcher(
-             query, text, false /* use_edit_distance */,
-             0.1 /*num_matching_blocks_penalty*/)
+  return string_matching::SequenceMatcher(query, text,
+                                          false /* use_edit_distance */,
+                                          0.1 /*num_matching_blocks_penalty*/)
       .Ratio();
 }
 
diff --git a/chromeos/ash/components/local_search_service/shared_structs.cc b/chromeos/ash/components/local_search_service/shared_structs.cc
index c34dc90..de5a557 100644
--- a/chromeos/ash/components/local_search_service/shared_structs.cc
+++ b/chromeos/ash/components/local_search_service/shared_structs.cc
@@ -9,8 +9,8 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "chromeos/ash/components/local_search_service/linear_map_search.h"
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
diff --git a/chromeos/components/string_matching/BUILD.gn b/chromeos/ash/components/string_matching/BUILD.gn
similarity index 94%
rename from chromeos/components/string_matching/BUILD.gn
rename to chromeos/ash/components/string_matching/BUILD.gn
index 0080ca9..0f33ed56 100644
--- a/chromeos/components/string_matching/BUILD.gn
+++ b/chromeos/ash/components/string_matching/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
-assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+assert(is_chromeos_ash)
 
 source_set("string_matching") {
   sources = [
diff --git a/chromeos/components/string_matching/DEPS b/chromeos/ash/components/string_matching/DEPS
similarity index 100%
rename from chromeos/components/string_matching/DEPS
rename to chromeos/ash/components/string_matching/DEPS
diff --git a/chromeos/components/string_matching/OWNERS b/chromeos/ash/components/string_matching/OWNERS
similarity index 100%
rename from chromeos/components/string_matching/OWNERS
rename to chromeos/ash/components/string_matching/OWNERS
diff --git a/chromeos/components/string_matching/README.md b/chromeos/ash/components/string_matching/README.md
similarity index 100%
rename from chromeos/components/string_matching/README.md
rename to chromeos/ash/components/string_matching/README.md
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc
similarity index 96%
rename from chromeos/components/string_matching/fuzzy_tokenized_string_match.cc
rename to chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc
index dfc0517..5dbb3af 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc
+++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
 
 #include <algorithm>
 #include <cmath>
@@ -16,13 +16,13 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/components/string_matching/prefix_matcher.h"
-#include "chromeos/components/string_matching/sequence_matcher.h"
+#include "chromeos/ash/components/string_matching/prefix_matcher.h"
+#include "chromeos/ash/components/string_matching/sequence_matcher.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
+
 constexpr double kMinScore = 0.0;
 constexpr double kMaxScore = 1.0;
 
@@ -35,6 +35,7 @@
   std::sort(result.begin(), result.end());
   return result;
 }
+
 }  // namespace
 
 FuzzyTokenizedStringMatch::~FuzzyTokenizedStringMatch() {}
@@ -245,7 +246,7 @@
 
 double FuzzyTokenizedStringMatch::PrefixMatcher(const TokenizedString& query,
                                                 const TokenizedString& text) {
-  chromeos::string_matching::PrefixMatcher match(query, text);
+  string_matching::PrefixMatcher match(query, text);
   match.Match();
   return 1.0 - std::pow(0.5, match.relevance());
 }
@@ -310,5 +311,4 @@
   return relevance_;
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match.h b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h
similarity index 92%
rename from chromeos/components/string_matching/fuzzy_tokenized_string_match.h
rename to chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h
index a231775..298cfaa 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match.h
+++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
 
 #include "base/gtest_prod_util.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "ui/gfx/range/range.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // FuzzyTokenizedStringMatch takes two tokenized strings: one as the text and
 // the other one as the query. It matches the query against the text,
@@ -109,7 +108,6 @@
   Hits hits_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_FUZZY_TOKENIZED_STRING_MATCH_H_
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
similarity index 98%
rename from chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
rename to chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
index 3e22e945..6b60ebc 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
+++ b/chromeos/ash/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
@@ -2,17 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/fuzzy_tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/components/string_matching/sequence_matcher.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/sequence_matcher.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
 
@@ -1029,5 +1028,4 @@
   EXPECT_EQ(match.hits()[0].end(), 3u);
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/prefix_matcher.cc b/chromeos/ash/components/string_matching/prefix_matcher.cc
similarity index 94%
rename from chromeos/components/string_matching/prefix_matcher.cc
rename to chromeos/ash/components/string_matching/prefix_matcher.cc
index ae033c31..b3c5b22 100644
--- a/chromeos/components/string_matching/prefix_matcher.cc
+++ b/chromeos/ash/components/string_matching/prefix_matcher.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/prefix_matcher.h"
+#include "chromeos/ash/components/string_matching/prefix_matcher.h"
 
 #include "base/check.h"
-#include "chromeos/components/string_matching/tokenized_string.h"
-#include "chromeos/components/string_matching/tokenized_string_char_iterator.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_char_iterator.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
+
 // TODO(crbug.com/1336160): Add unit tests.
 //
 // TODO(crbug.com/1336160): Paradigm shift 1: Reconsider the value of
@@ -64,6 +64,7 @@
 
 // A relevance score that represents no match.
 const double kNoMatchScore = 0.0;
+
 }  // namespace
 
 PrefixMatcher::PrefixMatcher(const TokenizedString& query,
@@ -175,5 +176,4 @@
   states_.pop_back();
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/prefix_matcher.h b/chromeos/ash/components/string_matching/prefix_matcher.h
similarity index 84%
rename from chromeos/components/string_matching/prefix_matcher.h
rename to chromeos/ash/components/string_matching/prefix_matcher.h
index 209d91c..9311147e 100644
--- a/chromeos/components/string_matching/prefix_matcher.h
+++ b/chromeos/ash/components/string_matching/prefix_matcher.h
@@ -2,15 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
 
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_char_iterator.h"
 
-#include "chromeos/components/string_matching/tokenized_string_char_iterator.h"
-
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // PrefixMatcher matches the chars of a given query as prefix of tokens in
 // a given text or as prefix of the acronyms of those text tokens.
@@ -83,7 +81,6 @@
   Hits current_hits_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_H_
diff --git a/chromeos/components/string_matching/sequence_matcher.cc b/chromeos/ash/components/string_matching/sequence_matcher.cc
similarity index 97%
rename from chromeos/components/string_matching/sequence_matcher.cc
rename to chromeos/ash/components/string_matching/sequence_matcher.cc
index f21d41de..faccbcf1d 100644
--- a/chromeos/components/string_matching/sequence_matcher.cc
+++ b/chromeos/ash/components/string_matching/sequence_matcher.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/sequence_matcher.h"
+#include "chromeos/ash/components/string_matching/sequence_matcher.h"
 
 #include <algorithm>
 #include <cmath>
@@ -10,16 +10,17 @@
 
 #include "base/check_op.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
+
 using Match = SequenceMatcher::Match;
 using Matches = std::vector<Match>;
 
 bool CompareMatches(const Match& m1, const Match& m2) {
   return m1.pos_first_string < m2.pos_first_string;
 }
+
 }  // namespace
 
 SequenceMatcher::Match::Match() = default;
@@ -248,5 +249,4 @@
   return block_matching_ratio_;
 }
 
-}  //  namespace string_matching
-}  //  namespace chromeos
+}  //  namespace ash::string_matching
diff --git a/chromeos/components/string_matching/sequence_matcher.h b/chromeos/ash/components/string_matching/sequence_matcher.h
similarity index 92%
rename from chromeos/components/string_matching/sequence_matcher.h
rename to chromeos/ash/components/string_matching/sequence_matcher.h
index 5e3285d5..d745871 100644
--- a/chromeos/components/string_matching/sequence_matcher.h
+++ b/chromeos/ash/components/string_matching/sequence_matcher.h
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
 
 #include <string>
 #include <unordered_map>
 #include <vector>
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // Performs the calculation of similarity level between 2 strings. This class's
 // functionality is inspired by python's difflib.SequenceMatcher library.
@@ -97,7 +96,6 @@
   std::vector<int> dp_common_string_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_SEQUENCE_MATCHER_H_
diff --git a/chromeos/components/string_matching/sequence_matcher_unittest.cc b/chromeos/ash/components/string_matching/sequence_matcher_unittest.cc
similarity index 96%
rename from chromeos/components/string_matching/sequence_matcher_unittest.cc
rename to chromeos/ash/components/string_matching/sequence_matcher_unittest.cc
index b150e10..c0c69e1 100644
--- a/chromeos/components/string_matching/sequence_matcher_unittest.cc
+++ b/chromeos/ash/components/string_matching/sequence_matcher_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/sequence_matcher.h"
+#include "chromeos/ash/components/string_matching/sequence_matcher.h"
 
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
+
 constexpr bool kDefaultUseEditDistance = false;
 
 using Match = SequenceMatcher::Match;
@@ -19,6 +19,7 @@
          match1.pos_second_string == match2.pos_second_string &&
          match1.length == match2.length;
 }
+
 }  // namespace
 
 class SequenceMatcherTest : public testing::Test {};
@@ -175,5 +176,4 @@
             0.0);
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/term_break_iterator.cc b/chromeos/ash/components/string_matching/term_break_iterator.cc
similarity index 92%
rename from chromeos/components/string_matching/term_break_iterator.cc
rename to chromeos/ash/components/string_matching/term_break_iterator.cc
index 00b9904..e1b6a24e 100644
--- a/chromeos/components/string_matching/term_break_iterator.cc
+++ b/chromeos/ash/components/string_matching/term_break_iterator.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/term_break_iterator.h"
+#include "chromeos/ash/components/string_matching/term_break_iterator.h"
 
 #include <ostream>
 
@@ -12,8 +12,7 @@
 #include "base/strings/string_util.h"
 #include "third_party/icu/source/common/unicode/uchar.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 TermBreakIterator::TermBreakIterator(const std::u16string& word)
     : word_(word),
@@ -76,5 +75,4 @@
   return STATE_CHAR;
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/term_break_iterator.h b/chromeos/ash/components/string_matching/term_break_iterator.h
similarity index 81%
rename from chromeos/components/string_matching/term_break_iterator.h
rename to chromeos/ash/components/string_matching/term_break_iterator.h
index d9e123b0..46f20e7 100644
--- a/chromeos/components/string_matching/term_break_iterator.h
+++ b/chromeos/ash/components/string_matching/term_break_iterator.h
@@ -2,22 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
 
 #include <stddef.h>
 
 #include <memory>
 #include <string>
 
-namespace base {
-namespace i18n {
+namespace base::i18n {
 class UTF16CharIterator;
 }
-}  // namespace base
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // TermBreakIterator breaks terms out of a word. Terms are broken on
 // camel case boundaries and alpha/number boundaries. Numbers are defined
@@ -68,7 +65,6 @@
   State state_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TERM_BREAK_ITERATOR_H_
diff --git a/chromeos/components/string_matching/term_break_iterator_unittest.cc b/chromeos/ash/components/string_matching/term_break_iterator_unittest.cc
similarity index 93%
rename from chromeos/components/string_matching/term_break_iterator_unittest.cc
rename to chromeos/ash/components/string_matching/term_break_iterator_unittest.cc
index b4ce684..f4002f29 100644
--- a/chromeos/components/string_matching/term_break_iterator_unittest.cc
+++ b/chromeos/ash/components/string_matching/term_break_iterator_unittest.cc
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/term_break_iterator.h"
+#include "chromeos/ash/components/string_matching/term_break_iterator.h"
 
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 TEST(TermBreakIteratorTest, EmptyWord) {
   std::u16string empty;
@@ -83,5 +82,4 @@
   EXPECT_FALSE(iter.Advance());  // Test unexpected advance after end.
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string.cc b/chromeos/ash/components/string_matching/tokenized_string.cc
similarity index 91%
rename from chromeos/components/string_matching/tokenized_string.cc
rename to chromeos/ash/components/string_matching/tokenized_string.cc
index 7be2e73..2094d31 100644
--- a/chromeos/components/string_matching/tokenized_string.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 
 #include <stddef.h>
 
@@ -12,12 +12,11 @@
 #include "base/notreached.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
-#include "chromeos/components/string_matching/term_break_iterator.h"
+#include "chromeos/ash/components/string_matching/term_break_iterator.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
-using base::i18n::BreakIterator;
+using ::base::i18n::BreakIterator;
 
 TokenizedString::TokenizedString(const std::u16string& text, Mode mode)
     : text_(text) {
@@ -104,5 +103,4 @@
   }
 }
 
-}  //  namespace string_matching
-}  //  namespace chromeos
+}  //  namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string.h b/chromeos/ash/components/string_matching/tokenized_string.h
similarity index 80%
rename from chromeos/components/string_matching/tokenized_string.h
rename to chromeos/ash/components/string_matching/tokenized_string.h
index e00902a..7071168 100644
--- a/chromeos/components/string_matching/tokenized_string.h
+++ b/chromeos/ash/components/string_matching/tokenized_string.h
@@ -2,16 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
 
 #include <string>
 #include <vector>
 
 #include "ui/gfx/range/range.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // TokenizedString takes a string and breaks it down into token words.
 class TokenizedString {
@@ -51,7 +50,6 @@
   Mappings mappings_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_H_
diff --git a/chromeos/components/string_matching/tokenized_string_char_iterator.cc b/chromeos/ash/components/string_matching/tokenized_string_char_iterator.cc
similarity index 92%
rename from chromeos/components/string_matching/tokenized_string_char_iterator.cc
rename to chromeos/ash/components/string_matching/tokenized_string_char_iterator.cc
index 0fb6b70..31746191 100644
--- a/chromeos/components/string_matching/tokenized_string_char_iterator.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_char_iterator.cc
@@ -2,14 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string_char_iterator.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_char_iterator.h"
 
 #include "base/check.h"
 #include "base/i18n/char_iterator.h"
 #include "third_party/icu/source/common/unicode/utf16.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 TokenizedStringCharIterator::State::State() : token_index(0u), char_index(0) {}
 
@@ -87,5 +86,4 @@
       std::make_unique<base::i18n::UTF16CharIterator>(tokens_[current_token_]);
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string_char_iterator.h b/chromeos/ash/components/string_matching/tokenized_string_char_iterator.h
similarity index 80%
rename from chromeos/components/string_matching/tokenized_string_char_iterator.h
rename to chromeos/ash/components/string_matching/tokenized_string_char_iterator.h
index dbd60bf3..20322304 100644
--- a/chromeos/components/string_matching/tokenized_string_char_iterator.h
+++ b/chromeos/ash/components/string_matching/tokenized_string_char_iterator.h
@@ -2,24 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
 
 #include <stddef.h>
 #include <stdint.h>
 
 #include <memory>
 
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 
-namespace base {
-namespace i18n {
+namespace base::i18n {
 class UTF16CharIterator;
 }
-}  // namespace base
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 // An UTF16 char iterator for a TokenizedString.
 class TokenizedStringCharIterator {
@@ -78,7 +75,6 @@
   std::unique_ptr<base::i18n::UTF16CharIterator> current_token_iter_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_CHAR_ITERATOR_H_
diff --git a/chromeos/components/string_matching/tokenized_string_char_iterator_unittest.cc b/chromeos/ash/components/string_matching/tokenized_string_char_iterator_unittest.cc
similarity index 95%
rename from chromeos/components/string_matching/tokenized_string_char_iterator_unittest.cc
rename to chromeos/ash/components/string_matching/tokenized_string_char_iterator_unittest.cc
index 9693548..8ae80534 100644
--- a/chromeos/components/string_matching/tokenized_string_char_iterator_unittest.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_char_iterator_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string_char_iterator.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_char_iterator.h"
 
 #include <string>
 #include <vector>
@@ -12,8 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
 
@@ -147,5 +146,4 @@
   TestFirstTwoCharInEveryToken(text, "f0! a1 s9! i10");
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string_fuzzer.cc b/chromeos/ash/components/string_matching/tokenized_string_fuzzer.cc
similarity index 78%
rename from chromeos/components/string_matching/tokenized_string_fuzzer.cc
rename to chromeos/ash/components/string_matching/tokenized_string_fuzzer.cc
index 7ca2881..b3b4f45 100644
--- a/chromeos/components/string_matching/tokenized_string_fuzzer.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_fuzzer.cc
@@ -4,7 +4,7 @@
 
 #include <string>
 
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   if (size < 1 || size % 2 != 0)
@@ -13,7 +13,7 @@
   // Test for std::u16string if size is even.
   std::u16string string_input16(reinterpret_cast<const char16_t*>(data),
                                 size / 2);
-  chromeos::string_matching::TokenizedString tokenized_string_from_string16(
+  ash::string_matching::TokenizedString tokenized_string_from_string16(
       string_input16);
   return 0;
 }
diff --git a/chromeos/components/string_matching/tokenized_string_match.cc b/chromeos/ash/components/string_matching/tokenized_string_match.cc
similarity index 91%
rename from chromeos/components/string_matching/tokenized_string_match.cc
rename to chromeos/ash/components/string_matching/tokenized_string_match.cc
index c16852b..8b00d19 100644
--- a/chromeos/components/string_matching/tokenized_string_match.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_match.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 
 #include <stddef.h>
 
@@ -10,17 +10,18 @@
 
 #include "base/i18n/string_search.h"
 #include "base/strings/string_util.h"
-#include "chromeos/components/string_matching/prefix_matcher.h"
+#include "chromeos/ash/components/string_matching/prefix_matcher.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
+
 // Used for each character if there is no prefix match.
 const double kIsSubstringMultiplier = 0.4;
 
 // A relevance score that represents no match.
 const double kNoMatchScore = 0.0;
+
 }  // namespace
 
 TokenizedStringMatch::TokenizedStringMatch() : relevance_(kNoMatchScore) {}
@@ -83,5 +84,4 @@
   return Calculate(tokenized_query, tokenized_text);
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string_match.h b/chromeos/ash/components/string_matching/tokenized_string_match.h
similarity index 83%
rename from chromeos/components/string_matching/tokenized_string_match.h
rename to chromeos/ash/components/string_matching/tokenized_string_match.h
index 8051e2d..78746ce3 100644
--- a/chromeos/components/string_matching/tokenized_string_match.h
+++ b/chromeos/ash/components/string_matching/tokenized_string_match.h
@@ -2,16 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
-#define CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
+#define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
 
 #include <string>
 #include <vector>
 
 #include "ui/gfx/range/range.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 class TokenizedString;
 
@@ -51,7 +50,6 @@
   Hits hits_;
 };
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
 
-#endif  // CHROMEOS_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_TOKENIZED_STRING_MATCH_H_
diff --git a/chromeos/components/string_matching/tokenized_string_match_unittest.cc b/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc
similarity index 96%
rename from chromeos/components/string_matching/tokenized_string_match_unittest.cc
rename to chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc
index 51c227e..8ee05a80 100644
--- a/chromeos/components/string_matching/tokenized_string_match_unittest.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string_match.h"
+#include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 
 #include <stddef.h>
 
@@ -12,8 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
 
@@ -148,5 +147,4 @@
   }
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/string_matching/tokenized_string_unittest.cc b/chromeos/ash/components/string_matching/tokenized_string_unittest.cc
similarity index 95%
rename from chromeos/components/string_matching/tokenized_string_unittest.cc
rename to chromeos/ash/components/string_matching/tokenized_string_unittest.cc
index cc831e4..bd436b5f 100644
--- a/chromeos/components/string_matching/tokenized_string_unittest.cc
+++ b/chromeos/ash/components/string_matching/tokenized_string_unittest.cc
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/string_matching/tokenized_string.h"
+#include "chromeos/ash/components/string_matching/tokenized_string.h"
 
 #include <stddef.h>
 
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chromeos {
-namespace string_matching {
+namespace ash::string_matching {
 
 namespace {
 
@@ -27,6 +26,7 @@
   }
   return str;
 }
+
 }  // namespace
 
 TEST(TokenizedStringTest, Empty) {
@@ -121,5 +121,4 @@
   }
 }
 
-}  // namespace string_matching
-}  // namespace chromeos
+}  // namespace ash::string_matching
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn
index 47cecd37..a2614327 100644
--- a/chromeos/components/BUILD.gn
+++ b/chromeos/components/BUILD.gn
@@ -27,7 +27,6 @@
     "//chromeos/components/quick_answers:unit_tests",
     "//chromeos/components/security_token_pin:unit_tests",
     "//chromeos/components/sensors:unit_tests",
-    "//chromeos/components/string_matching:unit_tests",
     "//chromeos/components/sync_wifi:unit_tests",
     "//mojo/core/embedder",
     "//ui/base:base",
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index ac095f88..60576b21 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-105-5161.0-1658138909-benchmark-105.0.5195.5-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-105-5187.0-1658746147-benchmark-105.0.5195.6-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index d397925cf..aac543b 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-105-5161.0-1658139264-benchmark-105.0.5195.5-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-105-5187.0-1658744978-benchmark-105.0.5195.6-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index f50b6ec..4b5e893 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-105-5161.0-1658138909-benchmark-105.0.5195.3-r1.orderfile.xz
+chromeos-chrome-orderfile-field-105-5161.0-1658138909-benchmark-105.0.5195.4-r1.orderfile.xz
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index b064a39..30f8353 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -181,12 +181,6 @@
   "assistant.StartupInSignedOutMode",
   "login.ChangePassword",
 
-  # https://crbug.com/1322572
-  "policy.NotificationsAllowedForUrls",
-  "policy.NotificationsBlockedForUrls",
-  "policy.PolicyRefreshRate",
-  "policy.PopupsForURLCheck.allowlist",
-
   # https://crbug.com/1326279
   "policy.AccessibilityPolicies.focus_highlight",
 
@@ -196,18 +190,12 @@
   # https://crbug.com/1326403
   "policy.AccessibilityPolicies.large_cursor",
 
-  # https://crbug.com/1327171
-  "policy.PopupsForURLCheck.default",
-
   # https://crbug.com/1327345
   "policy.ChromePolicyPageStatusTimestamps.ash",
 
   # https://crbug.com/1327361
   "policy.FullscreenAllowed",
 
-  # https://crbug.com/1328128
-  "policy.PopupsForURLCheck.blocklist",
-
   # https://crbug.com/1329734
   "health.DiagnosticsList",
   "health.DiagnosticsCancel.urandom",
@@ -226,9 +214,31 @@
   "health.DiagnosticsRun.dns_resolution",
   "health.DiagnosticsRun.dns_resolver_present",
 
+  # http://b234699971
+  "crostini.AppGeditUnshareFolder",
+
   # b/235279574
   "wmp.DragAndDropWindow",
 
+  # http://b/236312054
+  "crostini.AppGeditFilesharing",
+  "crostini.AppGeditFilesharing.stable",
+  "crostini.AppGeditFilesharing.clamshell_stable",
+
+  # http://b/236710501
+  "crostini.AppAndroidStudio.stable",
+  "crostini.AppGeditUnshareFolder.stable",
+  "crostini.AppGeditUnshareFolder.clamshell_stable",
+
+  # http://crbug.com/1339132
+  "crostini.AppEclipse",
+  "crostini.AppEmacs",
+  "crostini.AppVscode",
+  "crostini.BasicLxdNext.stable",
+  "crostini.RestartApp",
+  "crostini.RestartApp.stable",
+  "crostini.RestartApp.clamshell_stable",
+
   # http://b/238600197
   "crostini.FilesAppWatch.buster_stable",
 
diff --git a/components/autofill_assistant/android/BUILD.gn b/components/autofill_assistant/android/BUILD.gn
index dccfe9b..2eaeeca 100644
--- a/components/autofill_assistant/android/BUILD.gn
+++ b/components/autofill_assistant/android/BUILD.gn
@@ -23,6 +23,7 @@
     "//build/android:build_java",
     "//components/autofill/android:autofill_java",
     "//components/autofill/android:prefeditor_autofill_java",
+    "//components/autofill_assistant/guided_browsing/android:java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/modaldialog/android:java",
     "//components/browser_ui/settings/android:java",
@@ -139,6 +140,9 @@
     "java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayEventFilter.java",
     "java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayImage.java",
     "java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayModel.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeCameraScanModelWrapper.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeNativeDelegate.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeUtil.java",
     "java/src/org/chromium/components/autofill_assistant/trigger_scripts/AssistantTriggerScript.java",
     "java/src/org/chromium/components/autofill_assistant/trigger_scripts/AssistantTriggerScriptBridge.java",
     "java/src/org/chromium/components/autofill_assistant/user_data/AssistantChoiceList.java",
@@ -303,6 +307,9 @@
     "java/src/org/chromium/components/autofill_assistant/onboarding/BaseOnboardingCoordinator.java",
     "java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayDelegate.java",
     "java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayModel.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeCameraScanModelWrapper.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeNativeDelegate.java",
+    "java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeUtil.java",
     "java/src/org/chromium/components/autofill_assistant/trigger_scripts/AssistantTriggerScriptBridge.java",
     "java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataModel.java",
     "java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java",
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeCameraScanModelWrapper.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeCameraScanModelWrapper.java
new file mode 100644
index 0000000..83dde71a
--- /dev/null
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeCameraScanModelWrapper.java
@@ -0,0 +1,68 @@
+// 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.components.autofill_assistant.qr_code;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.camera_scan.AssistantQrCodeCameraScanModel;
+
+/**
+ * Wrapper around the |AssistantQrCodeCameraScanModel| to manage the state for the QR Code Camera
+ * Scan UI from the native code.
+ */
+@JNINamespace("autofill_assistant")
+public class AssistantQrCodeCameraScanModelWrapper {
+    private final AssistantQrCodeCameraScanModel mCameraScanModel;
+
+    /**
+     * The AssistantQrCodeCameraScanWrapperModel constructor.
+     */
+    @CalledByNative
+    public AssistantQrCodeCameraScanModelWrapper() {
+        mCameraScanModel = new AssistantQrCodeCameraScanModel();
+    }
+
+    /**
+     * Returns the underlying AssistantQrCodeCameraScanModel object.
+     */
+    AssistantQrCodeCameraScanModel getCameraScanModel() {
+        return mCameraScanModel;
+    }
+
+    @CalledByNative
+    private void setDelegate(AssistantQrCodeNativeDelegate delegate) {
+        mCameraScanModel.setDelegate(delegate);
+    }
+
+    @CalledByNative
+    private void setToolbarTitle(String text) {
+        mCameraScanModel.setToolbarTitle(text);
+    }
+
+    @CalledByNative
+    private void setPermissionText(String text) {
+        mCameraScanModel.setPermissionText(text);
+    }
+
+    @CalledByNative
+    private void setPermissionButtonText(String text) {
+        mCameraScanModel.setPermissionButtonText(text);
+    }
+
+    @CalledByNative
+    private void setOpenSettingsText(String text) {
+        mCameraScanModel.setOpenSettingsText(text);
+    }
+
+    @CalledByNative
+    private void setOpenSettingsButtonText(String text) {
+        mCameraScanModel.setOpenSettingsButtonText(text);
+    }
+
+    @CalledByNative
+    private void setOverlayTitle(String text) {
+        mCameraScanModel.setOverlayTitle(text);
+    }
+}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeNativeDelegate.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeNativeDelegate.java
new file mode 100644
index 0000000..0261d11
--- /dev/null
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeNativeDelegate.java
@@ -0,0 +1,73 @@
+// 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.components.autofill_assistant.qr_code;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeDelegate;
+
+/**
+ * Delegate for Assistant QR Code Scan actions which forwards events to a native counterpart.
+ */
+@JNINamespace("autofill_assistant")
+public class AssistantQrCodeNativeDelegate implements AssistantQrCodeDelegate {
+    private long mNativeAssistantQrCodeNativeDelegate;
+
+    @CalledByNative
+    private AssistantQrCodeNativeDelegate(long nativeAssistantQrCodeDelegate) {
+        mNativeAssistantQrCodeNativeDelegate = nativeAssistantQrCodeDelegate;
+    }
+
+    @Override
+    public void onScanResult(String value) {
+        if (mNativeAssistantQrCodeNativeDelegate != 0) {
+            AssistantQrCodeNativeDelegateJni.get().onScanResult(
+                    mNativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate.this,
+                    value);
+        }
+    }
+
+    @Override
+    public void onScanCancelled() {
+        if (mNativeAssistantQrCodeNativeDelegate != 0) {
+            AssistantQrCodeNativeDelegateJni.get().onScanCancelled(
+                    mNativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate.this);
+        }
+    }
+
+    @Override
+    public void onScanFailure() {
+        if (mNativeAssistantQrCodeNativeDelegate != 0) {
+            AssistantQrCodeNativeDelegateJni.get().onScanFailure(
+                    mNativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate.this);
+        }
+    }
+
+    @Override
+    public void onCameraError() {
+        if (mNativeAssistantQrCodeNativeDelegate != 0) {
+            AssistantQrCodeNativeDelegateJni.get().onCameraError(
+                    mNativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate.this);
+        }
+    }
+
+    @CalledByNative
+    private void clearNativePtr() {
+        mNativeAssistantQrCodeNativeDelegate = 0;
+    }
+
+    @NativeMethods
+    interface Natives {
+        void onScanResult(long nativeAssistantQrCodeNativeDelegate,
+                AssistantQrCodeNativeDelegate caller, String value);
+        void onScanCancelled(
+                long nativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate caller);
+        void onScanFailure(
+                long nativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate caller);
+        void onCameraError(
+                long nativeAssistantQrCodeNativeDelegate, AssistantQrCodeNativeDelegate caller);
+    }
+}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeUtil.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeUtil.java
new file mode 100644
index 0000000..b2d97833
--- /dev/null
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/qr_code/AssistantQrCodeUtil.java
@@ -0,0 +1,25 @@
+// 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.components.autofill_assistant.qr_code;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.autofill_assistant.AssistantDependencies;
+import org.chromium.components.autofill_assistant.guided_browsing.qr_code.AssistantQrCodeController;
+
+/**
+ * Util to expose QR Code Scan functionality from the |guided_browsing| component to the native
+ * code.
+ */
+@JNINamespace("autofill_assistant")
+public class AssistantQrCodeUtil {
+    /** Prompts the user for QR Code Scanning. */
+    @CalledByNative
+    private static void promptQrCodeCameraScan(AssistantDependencies dependencies,
+            AssistantQrCodeCameraScanModelWrapper cameraScanModelWrapper) {
+        AssistantQrCodeController.promptQrCodeCameraScan(dependencies.getActivity(),
+                dependencies.getWindowAndroid(), cameraScanModelWrapper.getCameraScanModel());
+    }
+}
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index 41517837..a378876 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -82,6 +82,8 @@
     "actions/presave_generated_password_action.h",
     "actions/prompt_action.cc",
     "actions/prompt_action.h",
+    "actions/prompt_qr_code_scan_action.cc",
+    "actions/prompt_qr_code_scan_action.h",
     "actions/register_password_reset_request_action.cc",
     "actions/register_password_reset_request_action.h",
     "actions/release_elements_action.cc",
@@ -481,6 +483,7 @@
     "actions/popup_message_action_unittest.cc",
     "actions/presave_generated_password_action_unittest.cc",
     "actions/prompt_action_unittest.cc",
+    "actions/prompt_qr_code_scan_action_unittest.cc",
     "actions/register_password_reset_request_action_unittest.cc",
     "actions/release_elements_action_unittest.cc",
     "actions/reset_pending_credentials_action_unittest.cc",
diff --git a/components/autofill_assistant/browser/actions/action.cc b/components/autofill_assistant/browser/actions/action.cc
index 681b7d9..732cf6ab 100644
--- a/components/autofill_assistant/browser/actions/action.cc
+++ b/components/autofill_assistant/browser/actions/action.cc
@@ -285,6 +285,9 @@
     case ActionProto::ActionInfoCase::kSetNativeChecked:
       out << "SetNativeChecked";
       break;
+    case ActionProto::ActionInfoCase::kPromptQrCodeScan:
+      out << "PromptQrCodeScan";
+      break;
     case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET:
       out << "ACTION_INFO_NOT_SET";
       break;
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index c7c9b21..66fba3c 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -60,6 +60,7 @@
 class FormProto;
 class FormProto_Result;
 class InfoBox;
+class PromptQrCodeScanProto;
 class UserAction;
 class UserData;
 class UserModel;
@@ -411,6 +412,16 @@
       base::RepeatingCallback<void(const FormProto_Result*)> changed_callback,
       base::OnceCallback<void(const ClientStatus&)> cancel_callback) = 0;
 
+  // Show QR Code Scan UI to the user. |callback| should be invoked with the
+  // scanned result or absl::nullopt and an appropriate client status.
+  virtual void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback) = 0;
+
+  // Clears the QR Code Scan Ui.
+  virtual void ClearQrCodeScanUi() = 0;
+
   // Force showing the UI if no UI is shown. This is useful when executing a
   // direct action which realizes it needs to interact with the user. Once
   // shown, the UI stays up until the end of the flow.
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index be48880..6322a514 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -175,6 +175,12 @@
            base::RepeatingCallback<void(const FormProto::Result*)>
                changed_callback,
            base::OnceCallback<void(const ClientStatus&)> cancel_callback));
+  MOCK_METHOD2(ShowQrCodeScanUi,
+               void(std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+                    base::OnceCallback<void(const ClientStatus&,
+                                            const absl::optional<ValueProto>&)>
+                        callback));
+  MOCK_METHOD0(ClearQrCodeScanUi, void());
   MOCK_CONST_METHOD0(GetUserModel, UserModel*());
   MOCK_METHOD1(WaitForWindowHeightChange,
                void(base::OnceCallback<void(const ClientStatus&)> callback));
diff --git a/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.cc b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.cc
new file mode 100644
index 0000000..24b49a71
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.cc
@@ -0,0 +1,72 @@
+// 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 "components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/user_action.h"
+#include "components/autofill_assistant/browser/user_model.h"
+
+namespace autofill_assistant {
+
+PromptQrCodeScanAction::PromptQrCodeScanAction(ActionDelegate* delegate,
+                                               const ActionProto& proto)
+    : Action(delegate, proto) {
+  DCHECK(proto_.has_prompt_qr_code_scan());
+}
+
+PromptQrCodeScanAction::~PromptQrCodeScanAction() = default;
+
+void PromptQrCodeScanAction::InternalProcessAction(
+    ProcessActionCallback callback) {
+  callback_ = std::move(callback);
+
+  if (proto_.prompt_qr_code_scan().output_client_memory_key().empty()) {
+    VLOG(1) << "Invalid action: output_client_memory_key not set";
+    EndAction(ClientStatus(INVALID_ACTION), /* value= */ absl::nullopt);
+    return;
+  }
+
+  // Validate that all UI strings are available.
+  const PromptQrCodeScanProto_CameraScanUiStrings* camera_scan_ui_strings =
+      &proto_.prompt_qr_code_scan().camera_scan_ui_strings();
+  if (camera_scan_ui_strings->title_text().empty() ||
+      camera_scan_ui_strings->permission_text().empty() ||
+      camera_scan_ui_strings->permission_button_text().empty() ||
+      camera_scan_ui_strings->open_settings_text().empty() ||
+      camera_scan_ui_strings->open_settings_button_text().empty() ||
+      camera_scan_ui_strings->camera_preview_instruction_text().empty()) {
+    VLOG(1) << "Invalid action: camera_scan_ui_strings not set";
+    EndAction(ClientStatus(INVALID_ACTION), /* value= */ absl::nullopt);
+    return;
+  }
+
+  delegate_->Prompt(/* user_actions = */ nullptr,
+                    /* disable_force_expand_sheet = */ false);
+  delegate_->ShowQrCodeScanUi(
+      std::make_unique<PromptQrCodeScanProto>(proto_.prompt_qr_code_scan()),
+      base::BindOnce(&PromptQrCodeScanAction::EndAction,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void PromptQrCodeScanAction::EndAction(
+    const ClientStatus& status,
+    const absl::optional<ValueProto>& value) {
+  if (value) {
+    delegate_->GetUserModel()->SetValue(
+        proto_.prompt_qr_code_scan().output_client_memory_key(), *value);
+  }
+
+  delegate_->ClearQrCodeScanUi();
+  delegate_->CleanUpAfterPrompt();
+  UpdateProcessedAction(status);
+  std::move(callback_).Run(std::move(processed_action_proto_));
+}
+
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h
new file mode 100644
index 0000000..2c81c9d
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h
@@ -0,0 +1,37 @@
+// 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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_QR_CODE_SCAN_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_QR_CODE_SCAN_ACTION_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace autofill_assistant {
+
+// An action to prompt QR Code Scanning.
+class PromptQrCodeScanAction : public Action {
+ public:
+  explicit PromptQrCodeScanAction(ActionDelegate* delegate,
+                                  const ActionProto& proto);
+
+  PromptQrCodeScanAction(const PromptQrCodeScanAction&) = delete;
+  PromptQrCodeScanAction& operator=(const PromptQrCodeScanAction&) = delete;
+
+  ~PromptQrCodeScanAction() override;
+
+ private:
+  // Overrides Action:
+  void InternalProcessAction(ProcessActionCallback callback) override;
+
+  void EndAction(const ClientStatus& status,
+                 const absl::optional<ValueProto>& value);
+
+  ProcessActionCallback callback_;
+  base::WeakPtrFactory<PromptQrCodeScanAction> weak_ptr_factory_{this};
+};
+
+}  // namespace autofill_assistant
+#endif  // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_QR_CODE_SCAN_ACTION_H_
diff --git a/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action_unittest.cc b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action_unittest.cc
new file mode 100644
index 0000000..4af525a
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/prompt_qr_code_scan_action_unittest.cc
@@ -0,0 +1,113 @@
+// 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 "components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/user_model.h"
+#include "components/autofill_assistant/browser/value_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+const char kDefaultQrCodeScanResult[] = "qr_code_scan_result";
+const char kDefaultOutputClientMemoryKey[] = "client_memory_key";
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Property;
+using ::testing::Return;
+
+class PromptQrCodeScanActionTest : public testing::Test {
+ public:
+  PromptQrCodeScanActionTest() = default;
+
+  void SetUp() override {
+    ON_CALL(mock_action_delegate_, GetUserModel)
+        .WillByDefault(Return(&user_model_));
+  }
+
+ protected:
+  void Run() {
+    ActionProto action_proto;
+    *action_proto.mutable_prompt_qr_code_scan() = proto_;
+    PromptQrCodeScanAction action(&mock_action_delegate_, action_proto);
+    action.ProcessAction(callback_.Get());
+  }
+
+  void setCameraScanUiStrings() {
+    proto_.mutable_camera_scan_ui_strings()->set_title_text("Title text");
+    proto_.mutable_camera_scan_ui_strings()->set_permission_text(
+        "Permission text");
+    proto_.mutable_camera_scan_ui_strings()->set_permission_button_text(
+        "Permission button text");
+    proto_.mutable_camera_scan_ui_strings()->set_open_settings_text(
+        "Open settings text");
+    proto_.mutable_camera_scan_ui_strings()->set_open_settings_button_text(
+        "Open settings button text");
+    proto_.mutable_camera_scan_ui_strings()
+        ->set_camera_preview_instruction_text(
+            "Camera preview instruction text");
+  }
+
+  UserModel user_model_;
+  MockActionDelegate mock_action_delegate_;
+  base::MockCallback<Action::ProcessActionCallback> callback_;
+  PromptQrCodeScanProto proto_;
+};
+
+TEST_F(PromptQrCodeScanActionTest, SuccessfullyPromptsAndGetQrCodeScanResult) {
+  proto_.set_output_client_memory_key(kDefaultOutputClientMemoryKey);
+  setCameraScanUiStrings();
+
+  InSequence seq;
+  EXPECT_CALL(mock_action_delegate_, Prompt).Times(1);
+  EXPECT_CALL(mock_action_delegate_, ShowQrCodeScanUi)
+      .WillOnce(
+          RunOnceCallback<1>(ClientStatus(ACTION_APPLIED),
+                             SimpleValue(std::string(kDefaultQrCodeScanResult),
+                                         /* is_client_side_only= */ true)));
+
+  EXPECT_CALL(mock_action_delegate_, ClearQrCodeScanUi).Times(1);
+  EXPECT_CALL(mock_action_delegate_, CleanUpAfterPrompt).Times(1);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  Run();
+
+  EXPECT_EQ(*user_model_.GetValue(kDefaultOutputClientMemoryKey),
+            SimpleValue(std::string(kDefaultQrCodeScanResult),
+                        /* is_client_side_only= */ true));
+}
+
+TEST_F(PromptQrCodeScanActionTest, FailsWhenOutputClientMemoryKeyIsNotSet) {
+  setCameraScanUiStrings();
+
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+
+  Run();
+}
+
+TEST_F(PromptQrCodeScanActionTest, FailsWhenCameraScanUiStringsAreNotSet) {
+  proto_.set_output_client_memory_key(kDefaultOutputClientMemoryKey);
+
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+
+  Run();
+}
+
+}  // namespace
+}  // namespace autofill_assistant
\ No newline at end of file
diff --git a/components/autofill_assistant/browser/android/BUILD.gn b/components/autofill_assistant/browser/android/BUILD.gn
index 0bb70199..5d44c2e13 100644
--- a/components/autofill_assistant/browser/android/BUILD.gn
+++ b/components/autofill_assistant/browser/android/BUILD.gn
@@ -18,6 +18,8 @@
     "assistant_header_model.h",
     "assistant_overlay_delegate.cc",
     "assistant_overlay_delegate.h",
+    "assistant_qr_code_native_delegate.cc",
+    "assistant_qr_code_native_delegate.h",
     "client_android.cc",
     "client_android.h",
     "features_android.cc",
diff --git a/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.cc b/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.cc
new file mode 100644
index 0000000..e66a4b5
--- /dev/null
+++ b/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.cc
@@ -0,0 +1,69 @@
+// 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 "components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.h"
+
+#include "components/autofill_assistant/android/jni_headers/AssistantQrCodeNativeDelegate_jni.h"
+#include "components/autofill_assistant/browser/android/ui_controller_android.h"
+#include "components/autofill_assistant/browser/android/ui_controller_android_utils.h"
+#include "components/autofill_assistant/browser/value_util.h"
+
+using base::android::AttachCurrentThread;
+
+namespace autofill_assistant {
+
+AssistantQrCodeNativeDelegate::AssistantQrCodeNativeDelegate(
+    UiControllerAndroid* ui_controller)
+    : ui_controller_(ui_controller) {
+  java_assistant_qr_code_native_delegate_ =
+      Java_AssistantQrCodeNativeDelegate_Constructor(
+          AttachCurrentThread(), reinterpret_cast<intptr_t>(this));
+}
+
+AssistantQrCodeNativeDelegate::~AssistantQrCodeNativeDelegate() {
+  Java_AssistantQrCodeNativeDelegate_clearNativePtr(
+      AttachCurrentThread(), java_assistant_qr_code_native_delegate_);
+}
+
+void AssistantQrCodeNativeDelegate::OnScanResult(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller,
+    const base::android::JavaParamRef<jstring>& jvalue) {
+  ui_controller_->OnQrCodeScanFinished(
+      ClientStatus(ACTION_APPLIED),
+      SimpleValue(ui_controller_android_utils::SafeConvertJavaStringToNative(
+                      env, jvalue),
+                  /*  is_client_side_only= */ true));
+}
+
+void AssistantQrCodeNativeDelegate::OnScanCancelled(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller) {
+  // TODO(b/238079150): Add custom ClientStatus
+  ui_controller_->OnQrCodeScanFinished(ClientStatus(OTHER_ACTION_STATUS),
+                                       absl::nullopt);
+}
+
+void AssistantQrCodeNativeDelegate::OnScanFailure(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller) {
+  // TODO(b/238079150): Add custom ClientStatus
+  ui_controller_->OnQrCodeScanFinished(ClientStatus(OTHER_ACTION_STATUS),
+                                       absl::nullopt);
+}
+
+void AssistantQrCodeNativeDelegate::OnCameraError(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller) {
+  // TODO(b/238079150): Add custom ClientStatus
+  ui_controller_->OnQrCodeScanFinished(ClientStatus(OTHER_ACTION_STATUS),
+                                       absl::nullopt);
+}
+
+base::android::ScopedJavaGlobalRef<jobject>
+AssistantQrCodeNativeDelegate::GetJavaObject() {
+  return java_assistant_qr_code_native_delegate_;
+}
+
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.h b/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.h
new file mode 100644
index 0000000..a3199ea
--- /dev/null
+++ b/components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.h
@@ -0,0 +1,57 @@
+// 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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ANDROID_ASSISTANT_QR_CODE_NATIVE_DELEGATE_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ANDROID_ASSISTANT_QR_CODE_NATIVE_DELEGATE_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/raw_ptr.h"
+
+namespace autofill_assistant {
+
+class UiControllerAndroid;
+
+// Delegate class for the QR Code. Receives events from the Java UI and
+// forwards them to the ui controller. This is the JNI bridge to
+// |AssistantQrCodeNativeDelegate.java|.
+class AssistantQrCodeNativeDelegate {
+ public:
+  // Note: |ui_controller| must outlive this instance.
+  explicit AssistantQrCodeNativeDelegate(UiControllerAndroid* ui_controller);
+  ~AssistantQrCodeNativeDelegate();
+
+  // This method is invoked from the java-side when QR code scanning is
+  // finished successfully.
+  void OnScanResult(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& jcaller,
+                    const base::android::JavaParamRef<jstring>& jvalue);
+
+  // This method is invoked from the java-side when QR code scanning is
+  // cancelled by the user.
+  void OnScanCancelled(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& jcaller);
+
+  // This method is invoked from the java-side when QR code scanning fails to
+  // give any output.
+  void OnScanFailure(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& jcaller);
+
+  // This method is invoked from the java-side when QR code scanning is
+  // interrupted by a camera error.
+  void OnCameraError(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& jcaller);
+
+  base::android::ScopedJavaGlobalRef<jobject> GetJavaObject();
+
+ private:
+  raw_ptr<UiControllerAndroid> ui_controller_;
+
+  // Java-side AssistantQrCodeNativeDelegate object.
+  base::android::ScopedJavaGlobalRef<jobject>
+      java_assistant_qr_code_native_delegate_;
+};
+
+}  // namespace autofill_assistant
+
+#endif  // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ANDROID_ASSISTANT_QR_CODE_NATIVE_DELEGATE_H_
diff --git a/components/autofill_assistant/browser/android/ui_controller_android.cc b/components/autofill_assistant/browser/android/ui_controller_android.cc
index fb9a722..9a69998 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android.cc
+++ b/components/autofill_assistant/browser/android/ui_controller_android.cc
@@ -29,6 +29,8 @@
 #include "components/autofill_assistant/android/jni_headers/AssistantModel_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantOverlayModel_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AssistantPlaceholdersConfiguration_jni.h"
+#include "components/autofill_assistant/android/jni_headers/AssistantQrCodeCameraScanModelWrapper_jni.h"
+#include "components/autofill_assistant/android/jni_headers/AssistantQrCodeUtil_jni.h"
 #include "components/autofill_assistant/android/jni_headers/AutofillAssistantUiController_jni.h"
 #include "components/autofill_assistant/browser/android/client_android.h"
 #include "components/autofill_assistant/browser/android/dependencies_android.h"
@@ -539,6 +541,12 @@
       /* screenshotMode */ 0);
 }
 
+void UiControllerAndroid::OnQrCodeScanFinished(
+    const ClientStatus& status,
+    const absl::optional<ValueProto>& value) {
+  ui_delegate_->OnQrCodeScanFinished(status, value);
+}
+
 void UiControllerAndroid::OnViewEvent(const EventHandler::EventKey& key) {
   ui_delegate_->DispatchEvent(key);
 }
@@ -656,6 +664,7 @@
   OnPersistentGenericUserInterfaceChanged(
       ui_delegate_->GetPersistentGenericUiProto());
   OnGenericUserInterfaceChanged(ui_delegate_->GetGenericUiProto());
+  OnQrCodeScanUiChanged(ui_delegate_->GetPromptQrCodeScanProto());
 
   std::vector<RectF> area;
   execution_delegate_->GetTouchableArea(&area);
@@ -1846,6 +1855,58 @@
   OnClientSettingsDisplayStringsChanged(settings);
 }
 
+void UiControllerAndroid::OnQrCodeScanUiChanged(
+    const PromptQrCodeScanProto* qr_code_scan) {
+  if (!qr_code_scan) {
+    qr_code_native_delegate_ = nullptr;
+    return;
+  }
+
+  JNIEnv* env = AttachCurrentThread();
+  qr_code_native_delegate_ =
+      std::make_unique<AssistantQrCodeNativeDelegate>(this);
+
+  const auto java_assistant_camera_scan_model_wrapper =
+      Java_AssistantQrCodeCameraScanModelWrapper_Constructor(env);
+
+  // Register qr_code_native_delegate_ as delegate for the QR Code Camera Scan
+  // UI
+  Java_AssistantQrCodeCameraScanModelWrapper_setDelegate(
+      env, java_assistant_camera_scan_model_wrapper,
+      qr_code_native_delegate_->GetJavaObject());
+
+  // Set UI strings in model
+  const PromptQrCodeScanProto_CameraScanUiStrings* camera_scan_ui_strings =
+      &qr_code_scan->camera_scan_ui_strings();
+  Java_AssistantQrCodeCameraScanModelWrapper_setToolbarTitle(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(env, camera_scan_ui_strings->title_text()));
+  Java_AssistantQrCodeCameraScanModelWrapper_setPermissionText(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(env, camera_scan_ui_strings->permission_text()));
+  Java_AssistantQrCodeCameraScanModelWrapper_setPermissionButtonText(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(
+          env, camera_scan_ui_strings->permission_button_text()));
+  Java_AssistantQrCodeCameraScanModelWrapper_setOpenSettingsText(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(env,
+                              camera_scan_ui_strings->open_settings_text()));
+  Java_AssistantQrCodeCameraScanModelWrapper_setOpenSettingsButtonText(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(
+          env, camera_scan_ui_strings->open_settings_button_text()));
+  Java_AssistantQrCodeCameraScanModelWrapper_setOverlayTitle(
+      env, java_assistant_camera_scan_model_wrapper,
+      ConvertUTF8ToJavaString(
+          env, camera_scan_ui_strings->camera_preview_instruction_text()));
+
+  Java_AssistantQrCodeUtil_promptQrCodeCameraScan(
+      env,
+      Java_AutofillAssistantUiController_getDependencies(env, java_object_),
+      java_assistant_camera_scan_model_wrapper);
+}
+
 void UiControllerAndroid::OnGenericUserInterfaceChanged(
     const GenericUserInterfaceProto* generic_ui) {
   // Try to inflate user interface from proto.
diff --git a/components/autofill_assistant/browser/android/ui_controller_android.h b/components/autofill_assistant/browser/android/ui_controller_android.h
index 72dec578..450afc5 100644
--- a/components/autofill_assistant/browser/android/ui_controller_android.h
+++ b/components/autofill_assistant/browser/android/ui_controller_android.h
@@ -19,6 +19,7 @@
 #include "components/autofill_assistant/browser/android/assistant_header_delegate.h"
 #include "components/autofill_assistant/browser/android/assistant_header_model.h"
 #include "components/autofill_assistant/browser/android/assistant_overlay_delegate.h"
+#include "components/autofill_assistant/browser/android/assistant_qr_code_native_delegate.h"
 #include "components/autofill_assistant/browser/android/dependencies_android.h"
 #include "components/autofill_assistant/browser/chip.h"
 #include "components/autofill_assistant/browser/details.h"
@@ -136,6 +137,8 @@
   void OnCollapseBottomSheet() override;
   void OnFormChanged(const FormProto* form,
                      const FormProto::Result* result) override;
+  void OnQrCodeScanUiChanged(
+      const PromptQrCodeScanProto* qr_code_scan) override;
   void OnGenericUserInterfaceChanged(
       const GenericUserInterfaceProto* generic_ui) override;
   void OnPersistentGenericUserInterfaceChanged(
@@ -151,6 +154,10 @@
   void OnHeaderFeedbackButtonClicked();
   void OnTtsButtonClicked();
 
+  // Called by AssistantQrCodeDelegate.
+  void OnQrCodeScanFinished(const ClientStatus& status,
+                            const absl::optional<ValueProto>& value);
+
   // Called by AssistantGenericUiDelegate:
   void OnViewEvent(const EventHandler::EventKey& key);
   void OnValueChanged(const std::string& identifier, const ValueProto& value);
@@ -250,6 +257,7 @@
   base::android::ScopedJavaLocalRef<jobject> GetDetailsModel();
   base::android::ScopedJavaLocalRef<jobject> GetInfoBoxModel();
   base::android::ScopedJavaLocalRef<jobject> GetCollectUserDataModel();
+  base::android::ScopedJavaLocalRef<jobject> GetQrCodeCameraScanWrapperModel();
   base::android::ScopedJavaLocalRef<jobject> GetFormModel();
   base::android::ScopedJavaLocalRef<jobject> GetGenericUiModel();
   base::android::ScopedJavaLocalRef<jobject> GetPersistentGenericUiModel();
@@ -320,6 +328,8 @@
 
   std::unique_ptr<AssistantHeaderModel> header_model_;
 
+  std::unique_ptr<AssistantQrCodeNativeDelegate> qr_code_native_delegate_;
+
   base::WeakPtrFactory<UiControllerAndroid> weak_ptr_factory_{this};
 };
 
diff --git a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc
index c354be7..8446437 100644
--- a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc
+++ b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc
@@ -142,6 +142,17 @@
   return true;
 }
 
+void FakeScriptExecutorUiDelegate::ShowQrCodeScanUi(
+    std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+    base::OnceCallback<void(const ClientStatus&,
+                            const absl::optional<ValueProto>&)> callback) {
+  show_qr_code_scan_ui_ = true;
+}
+
+void FakeScriptExecutorUiDelegate::ClearQrCodeScanUi() {
+  show_qr_code_scan_ui_ = false;
+}
+
 void FakeScriptExecutorUiDelegate::SetGenericUi(
     std::unique_ptr<GenericUserInterfaceProto> generic_ui,
     base::OnceCallback<void(const ClientStatus&)> end_action_callback,
diff --git a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h
index d6a64b5b..933f5b4 100644
--- a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h
+++ b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h
@@ -68,6 +68,12 @@
       std::unique_ptr<FormProto> form,
       base::RepeatingCallback<void(const FormProto::Result*)> changed_callback,
       base::OnceCallback<void(const ClientStatus&)> cancel_callback) override;
+  void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback)
+      override;
+  void ClearQrCodeScanUi() override;
   void SetExpandSheetForPromptAction(bool expand) override;
   void SetGenericUi(
       std::unique_ptr<GenericUserInterfaceProto> generic_ui,
@@ -111,6 +117,8 @@
     return interrupt_notification_history_;
   }
 
+  bool IsShowingQrCodeScanUi() { return show_qr_code_scan_ui_; }
+
  private:
   std::string status_message_;
   std::string tts_message_;
@@ -128,6 +136,7 @@
   bool expand_or_collapse_updated_ = false;
   bool expand_or_collapse_value_ = false;
   bool expand_sheet_for_prompt_ = true;
+  bool show_qr_code_scan_ui_ = false;
   std::unique_ptr<GenericUserInterfaceProto> persistent_generic_ui_;
   std::vector<InterruptNotification> interrupt_notification_history_;
 };
diff --git a/components/autofill_assistant/browser/headless/headless_ui_controller.cc b/components/autofill_assistant/browser/headless/headless_ui_controller.cc
index bff77466..29bbd3a 100644
--- a/components/autofill_assistant/browser/headless/headless_ui_controller.cc
+++ b/components/autofill_assistant/browser/headless/headless_ui_controller.cc
@@ -122,6 +122,16 @@
   VLOG(2) << "Unexpected UI method called: " << __func__;
   return false;
 }
+void HeadlessUiController::ShowQrCodeScanUi(
+    std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+    base::OnceCallback<void(const ClientStatus&,
+                            const absl::optional<ValueProto>&)> callback) {
+  VLOG(2) << "Unexpected UI method called: " << __func__;
+}
+
+void HeadlessUiController::ClearQrCodeScanUi() {
+  VLOG(2) << "Unexpected UI method called: " << __func__;
+}
 void HeadlessUiController::SetGenericUi(
     std::unique_ptr<GenericUserInterfaceProto> generic_ui,
     base::OnceCallback<void(const ClientStatus&)> end_action_callback,
diff --git a/components/autofill_assistant/browser/headless/headless_ui_controller.h b/components/autofill_assistant/browser/headless/headless_ui_controller.h
index 0ce8364..c1355a1 100644
--- a/components/autofill_assistant/browser/headless/headless_ui_controller.h
+++ b/components/autofill_assistant/browser/headless/headless_ui_controller.h
@@ -57,6 +57,12 @@
       std::unique_ptr<FormProto> form,
       base::RepeatingCallback<void(const FormProto::Result*)> changed_callback,
       base::OnceCallback<void(const ClientStatus&)> cancel_callback) override;
+  void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback)
+      override;
+  void ClearQrCodeScanUi() override;
   void SetGenericUi(
       std::unique_ptr<GenericUserInterfaceProto> generic_ui,
       base::OnceCallback<void(const ClientStatus&)> end_action_callback,
diff --git a/components/autofill_assistant/browser/mock_ui_controller_observer.h b/components/autofill_assistant/browser/mock_ui_controller_observer.h
index cbdffdb..ac9a243 100644
--- a/components/autofill_assistant/browser/mock_ui_controller_observer.h
+++ b/components/autofill_assistant/browser/mock_ui_controller_observer.h
@@ -47,6 +47,8 @@
   MOCK_METHOD0(OnCollapseBottomSheet, void());
   MOCK_METHOD2(OnFormChanged,
                void(const FormProto* form, const FormProto::Result* result));
+  MOCK_METHOD1(OnQrCodeScanUiChanged,
+               void(const PromptQrCodeScanProto* qr_code_scan));
   MOCK_METHOD1(OnGenericUserInterfaceChanged,
                void(const GenericUserInterfaceProto* generic_ui));
   MOCK_METHOD1(OnPersistentGenericUserInterfaceChanged,
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc
index dbbe934a..00f9a16 100644
--- a/components/autofill_assistant/browser/protocol_utils.cc
+++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -31,6 +31,7 @@
 #include "components/autofill_assistant/browser/actions/popup_message_action.h"
 #include "components/autofill_assistant/browser/actions/presave_generated_password_action.h"
 #include "components/autofill_assistant/browser/actions/prompt_action.h"
+#include "components/autofill_assistant/browser/actions/prompt_qr_code_scan_action.h"
 #include "components/autofill_assistant/browser/actions/register_password_reset_request_action.h"
 #include "components/autofill_assistant/browser/actions/release_elements_action.h"
 #include "components/autofill_assistant/browser/actions/reset_pending_credentials_action.h"
@@ -478,6 +479,8 @@
           base::BindOnce(&WebController::SetNativeChecked,
                          delegate->GetWebController()->GetWeakPtr(),
                          action.set_native_checked().checked()));
+    case ActionProto::ActionInfoCase::kPromptQrCodeScan:
+      return std::make_unique<PromptQrCodeScanAction>(delegate, action);
     case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET: {
       VLOG(1) << "Encountered action with ACTION_INFO_NOT_SET";
       return std::make_unique<UnsupportedAction>(delegate, action);
@@ -759,6 +762,10 @@
           action_id, bytes, error_message,
           proto.mutable_register_password_reset_request());
       break;
+    case ActionProto::ActionInfoCase::kPromptQrCodeScan:
+      success = ParseActionFromString(action_id, bytes, error_message,
+                                      proto.mutable_prompt_qr_code_scan());
+      break;
     case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET:
       // This is an "unknown action", handled as such in CreateAction.
       return proto;
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 901d256..fa49e26 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -716,6 +716,17 @@
                                std::move(cancel_callback));
 }
 
+void ScriptExecutor::ShowQrCodeScanUi(
+    std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+    base::OnceCallback<void(const ClientStatus&,
+                            const absl::optional<ValueProto>&)> callback) {
+  ui_delegate_->ShowQrCodeScanUi(std::move(qr_code_scan), std::move(callback));
+}
+
+void ScriptExecutor::ClearQrCodeScanUi() {
+  ui_delegate_->ClearQrCodeScanUi();
+}
+
 void ScriptExecutor::RequireUI() {
   delegate_->RequireUI();
 }
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 55d57ec..b8879ba2 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -244,6 +244,12 @@
       std::unique_ptr<FormProto> form,
       base::RepeatingCallback<void(const FormProto::Result*)> changed_callback,
       base::OnceCallback<void(const ClientStatus&)> cancel_callback) override;
+  void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback)
+      override;
+  void ClearQrCodeScanUi() override;
   void RequireUI() override;
   void SetGenericUi(
       std::unique_ptr<GenericUserInterfaceProto> generic_ui,
diff --git a/components/autofill_assistant/browser/script_executor_ui_delegate.h b/components/autofill_assistant/browser/script_executor_ui_delegate.h
index d9ff269..5ff267c 100644
--- a/components/autofill_assistant/browser/script_executor_ui_delegate.h
+++ b/components/autofill_assistant/browser/script_executor_ui_delegate.h
@@ -73,6 +73,15 @@
   // Set how the sheet should behave when entering a prompt state.
   virtual void SetExpandSheetForPromptAction(bool expand) = 0;
 
+  // Shows QR Code Scan UI to the user.
+  virtual void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback) = 0;
+
+  // Clears the QR Code Scan UI.
+  virtual void ClearQrCodeScanUi() = 0;
+
   // Sets the generic UI to show to the user.
   virtual void SetGenericUi(
       std::unique_ptr<GenericUserInterfaceProto> generic_ui,
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 35795e20..a750d95 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -2348,6 +2348,16 @@
             UserDataEventField::NONE);
 }
 
+TEST_F(ScriptExecutorTest, ShowQrCodeScanUi) {
+  executor_->ShowQrCodeScanUi(
+      std::make_unique<PromptQrCodeScanProto>(PromptQrCodeScanProto()),
+      base::DoNothing());
+  EXPECT_TRUE(ui_delegate_.IsShowingQrCodeScanUi());
+
+  executor_->ClearQrCodeScanUi();
+  EXPECT_FALSE(ui_delegate_.IsShowingQrCodeScanUi());
+}
+
 TEST_F(ScriptExecutorTest, MustUseBackendData) {
   delegate_.SetMustUseBackendData(true);
   EXPECT_TRUE(executor_->MustUseBackendData());
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index cab9551f..a1e9a9648 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -1071,6 +1071,7 @@
     ExternalActionProto external_action = 95;
     SetNativeValueProto set_native_value = 96;
     SetNativeCheckedProto set_native_checked = 97;
+    PromptQrCodeScanProto prompt_qr_code_scan = 98;
   }
 
   // Set to true to make the client remove any contextual information if the
@@ -1830,6 +1831,45 @@
   optional ClientSettingsProto client_settings = 1;
 }
 
+// Action to prompt QR Code Scanning. The action is used to scan a QR Code,
+// either via Camera Preview or Image Upload, and store the output in client
+// memory.
+message PromptQrCodeScanProto {
+  // Whether to trigger QR Code Scanning via Camera Preview or Image Upload.
+  optional bool use_gallery = 1;
+
+  // Key to store the QR Code scanning output in client memory. This is a
+  // mandatory field.
+  optional string output_client_memory_key = 2;
+
+  // UI strings shown to the user during QR Code Scanning via Camera Preview.
+  message CameraScanUiStrings {
+    // Text to be displayed as title on Toolbar.
+    optional string title_text = 1;
+
+    // Text to ask users to grant camera permission.
+    optional string permission_text = 2;
+
+    // Text on action button while asking users to grant camera permissions.
+    optional string permission_button_text = 3;
+
+    // Text to ask users to grant camera permissions by going into system
+    // settings.
+    optional string open_settings_text = 4;
+
+    // Text on action button while asking users to grant camera permissions by
+    // going into system settings.
+    optional string open_settings_button_text = 5;
+
+    // Instruction text shown during camera preview.
+    optional string camera_preview_instruction_text = 6;
+  }
+
+  // UI strings shown during camera scan. This is a mandatory field when QR Code
+  // Scanning via Camera Preview is to be triggered.
+  optional CameraScanUiStrings camera_scan_ui_strings = 3;
+}
+
 // Contain a localized text message from the server.
 message TellProto {
   message TextToSpeech {
diff --git a/components/autofill_assistant/browser/ui_controller.cc b/components/autofill_assistant/browser/ui_controller.cc
index 1b3a9d8..c26c2dd 100644
--- a/components/autofill_assistant/browser/ui_controller.cc
+++ b/components/autofill_assistant/browser/ui_controller.cc
@@ -444,6 +444,25 @@
   }
 }
 
+void UiController::ShowQrCodeScanUi(
+    std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+    base::OnceCallback<void(const ClientStatus&,
+                            const absl::optional<ValueProto>&)> callback) {
+  qr_code_scan_ = std::move(qr_code_scan);
+  qr_code_scan_callback_ = std::move(callback);
+  for (UiControllerObserver& observer : observers_) {
+    observer.OnQrCodeScanUiChanged(qr_code_scan_.get());
+  }
+}
+
+void UiController::ClearQrCodeScanUi() {
+  qr_code_scan_.reset();
+  qr_code_scan_callback_ = base::DoNothing();
+  for (UiControllerObserver& observer : observers_) {
+    observer.OnQrCodeScanUiChanged(nullptr);
+  }
+}
+
 void UiController::SetGenericUi(
     std::unique_ptr<GenericUserInterfaceProto> generic_ui,
     base::OnceCallback<void(const ClientStatus&)> end_action_callback,
@@ -678,6 +697,10 @@
   return &basic_interactions_;
 }
 
+const PromptQrCodeScanProto* UiController::GetPromptQrCodeScanProto() const {
+  return qr_code_scan_.get();
+}
+
 const GenericUserInterfaceProto* UiController::GetGenericUiProto() const {
   return generic_user_interface_.get();
 }
@@ -843,6 +866,14 @@
       UserDataFieldChange::ADDITIONAL_VALUES);
 }
 
+void UiController::OnQrCodeScanFinished(
+    const ClientStatus& status,
+    const absl::optional<ValueProto>& value) {
+  if (qr_code_scan_callback_) {
+    std::move(qr_code_scan_callback_).Run(status, value);
+  }
+}
+
 void UiController::HandleShippingAddressChange(
     std::unique_ptr<autofill::AutofillProfile> address,
     UserDataEventType event_type) {
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h
index 08a4984..b44b9c19f 100644
--- a/components/autofill_assistant/browser/ui_controller.h
+++ b/components/autofill_assistant/browser/ui_controller.h
@@ -93,6 +93,12 @@
       std::unique_ptr<FormProto> form,
       base::RepeatingCallback<void(const FormProto::Result*)> changed_callback,
       base::OnceCallback<void(const ClientStatus&)> cancel_callback) override;
+  void ShowQrCodeScanUi(
+      std::unique_ptr<PromptQrCodeScanProto> qr_code_scan,
+      base::OnceCallback<void(const ClientStatus&,
+                              const absl::optional<ValueProto>&)> callback)
+      override;
+  void ClearQrCodeScanUi() override;
   void SetGenericUi(
       std::unique_ptr<GenericUserInterfaceProto> generic_ui,
       base::OnceCallback<void(const ClientStatus&)> end_action_callback,
@@ -151,6 +157,8 @@
   void OnTtsButtonClicked() override;
   void SetAdditionalValue(const std::string& client_memory_key,
                           const ValueProto& value) override;
+  void OnQrCodeScanFinished(const ClientStatus& status,
+                            const absl::optional<ValueProto>& value) override;
   ConfigureBottomSheetProto::PeekMode GetPeekMode() override;
   BottomSheetState GetBottomSheetState() override;
   void SetBottomSheetState(BottomSheetState state) override;
@@ -164,6 +172,7 @@
   void RemoveObserver(const UiControllerObserver* observer) override;
   bool ShouldPromptActionExpandSheet() const override;
   BasicInteractions* GetBasicInteractions() override;
+  const PromptQrCodeScanProto* GetPromptQrCodeScanProto() const override;
   const GenericUserInterfaceProto* GetGenericUiProto() const override;
   const GenericUserInterfaceProto* GetPersistentGenericUiProto() const override;
   void OnKeyboardVisibilityChanged(bool visible) override;
@@ -324,6 +333,12 @@
   std::unique_ptr<AutofillAssistantTtsController> tts_controller_;
   TtsButtonState tts_button_state_ = TtsButtonState::DEFAULT;
 
+  // Only set during a PromptQrCodeScanAction.
+  std::unique_ptr<PromptQrCodeScanProto> qr_code_scan_;
+  base::OnceCallback<void(const ClientStatus&,
+                          const absl::optional<ValueProto>&)>
+      qr_code_scan_callback_;
+
   // Only set during a ShowGenericUiAction.
   std::unique_ptr<GenericUserInterfaceProto> generic_user_interface_;
 
diff --git a/components/autofill_assistant/browser/ui_controller_observer.h b/components/autofill_assistant/browser/ui_controller_observer.h
index 07dc7f0..1c45433 100644
--- a/components/autofill_assistant/browser/ui_controller_observer.h
+++ b/components/autofill_assistant/browser/ui_controller_observer.h
@@ -84,6 +84,10 @@
   virtual void OnFormChanged(const FormProto* form,
                              const FormProto::Result* result) = 0;
 
+  // Called when QR Code Scanning is prompted or cleared.
+  virtual void OnQrCodeScanUiChanged(
+      const PromptQrCodeScanProto* qr_code_scan) = 0;
+
   // Called when the generic user interface to show has been changed or cleared.
   virtual void OnGenericUserInterfaceChanged(
       const GenericUserInterfaceProto* generic_ui) = 0;
diff --git a/components/autofill_assistant/browser/ui_controller_unittest.cc b/components/autofill_assistant/browser/ui_controller_unittest.cc
index 8acb6eb..16c4e22 100644
--- a/components/autofill_assistant/browser/ui_controller_unittest.cc
+++ b/components/autofill_assistant/browser/ui_controller_unittest.cc
@@ -938,6 +938,41 @@
   EXPECT_TRUE(ui_controller_->ShouldPromptActionExpandSheet());
 }
 
+TEST_F(UiControllerTest, ShowQrCodeScanUi) {
+  EXPECT_CALL(mock_observer_, OnQrCodeScanUiChanged(NotNull()));
+
+  ui_controller_->ShowQrCodeScanUi(
+      std::make_unique<PromptQrCodeScanProto>(PromptQrCodeScanProto()),
+      base::DoNothing());
+}
+
+TEST_F(UiControllerTest, ClearQrCodeScanUi) {
+  EXPECT_CALL(mock_observer_, OnQrCodeScanUiChanged(nullptr));
+
+  ui_controller_->ClearQrCodeScanUi();
+}
+
+TEST_F(UiControllerTest, OnQrCodeScanFinished) {
+  base::MockCallback<base::OnceCallback<void(
+      const ClientStatus&, const absl::optional<ValueProto>&)>>
+      callback;
+  EXPECT_CALL(callback, Run)
+      .WillOnce([&](const ClientStatus& client_status,
+                    const absl::optional<ValueProto>& value) {
+        EXPECT_TRUE(client_status.ok());
+        EXPECT_EQ(value->strings().values(0),
+                  std::string("QR_CODE_SCAN_RESULT"));
+      });
+
+  ui_controller_->ShowQrCodeScanUi(
+      std::make_unique<PromptQrCodeScanProto>(PromptQrCodeScanProto()),
+      callback.Get());
+  ui_controller_->OnQrCodeScanFinished(
+      ClientStatus(ACTION_APPLIED),
+      SimpleValue(std::string("QR_CODE_SCAN_RESULT"),
+                  /* is_client_side_only= */ true));
+}
+
 TEST_F(UiControllerTest, SetGenericUi) {
   {
     testing::InSequence seq;
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h
index e3d3137e..cb090a4b 100644
--- a/components/autofill_assistant/browser/ui_delegate.h
+++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -124,6 +124,11 @@
   virtual void SetAdditionalValue(const std::string& client_memory_key,
                                   const ValueProto& value) = 0;
 
+  // Called when QR Code Scan Action is finished.
+  virtual void OnQrCodeScanFinished(
+      const ClientStatus& status,
+      const absl::optional<ValueProto>& value) = 0;
+
   // Peek mode state and whether it was changed automatically last time.
   virtual ConfigureBottomSheetProto::PeekMode GetPeekMode() = 0;
 
@@ -168,6 +173,9 @@
   // Whether the sheet should be auto expanded when entering the prompt state.
   virtual bool ShouldPromptActionExpandSheet() const = 0;
 
+  // Get PromptQrCodeScanProto, if any.
+  virtual const PromptQrCodeScanProto* GetPromptQrCodeScanProto() const = 0;
+
   // The generic user interface to show, if any.
   virtual const GenericUserInterfaceProto* GetGenericUiProto() const = 0;
 
diff --git a/components/history/core/browser/sync/history_sync_bridge.cc b/components/history/core/browser/sync/history_sync_bridge.cc
index 45f9ec1..add76ef0 100644
--- a/components/history/core/browser/sync/history_sync_bridge.cc
+++ b/components/history/core/browser/sync/history_sync_bridge.cc
@@ -326,33 +326,39 @@
       DLOG(ERROR) << "Skipping invalid visit, reason "
                   << static_cast<int>(*specifics_error);
       RecordSpecificsError(*specifics_error);
-      // If this was a newly-added visit, immediately untrack it again.
-      if (entity_change->type() == syncer::EntityChange::ACTION_ADD) {
-        change_processor()->UntrackEntityForClientTagHash(
-            entity_change->data().client_tag_hash);
-      }
+      continue;
+    }
+
+    if (specifics.originator_cache_guid() == GetLocalCacheGuid()) {
+      // This is likely a reflection, i.e. an update that came from this client.
+      // (Unless a different client is misbehaving and sending data with this
+      // client's cache GUID.) So no need to do anything with it; the data is
+      // already here.
+      // Note: For other data types, the processor filters out reflection
+      // updates before they reach the bridge, but here that's not possible
+      // because metadata is not tracked.
       continue;
     }
 
     switch (entity_change->type()) {
       case syncer::EntityChange::ACTION_ADD:
       case syncer::EntityChange::ACTION_UPDATE: {
-        // First try updating an existing row. In addition to actual updates,
-        // this can also happen during initial merge (if Sync was enabled before
-        // and this entity was already downloaded back then).
-        // TODO(crbug.com/1329131): ...or if the visit was untracked.
+        // First try updating an existing row. Since metadata isn't tracked for
+        // this data type, the processor can't distinguish "ADD" from "UPDATE".
+        // Note: Because metadata isn't tracked (and thus no version numbers
+        // exist), it's theoretically possible to receive an older version of an
+        // already-existing entity here. This should be very rare in practice
+        // and would be tricky to handle (would have to store version numbers
+        // elsewhere), so just ignore this case.
         if (UpdateEntityInBackend(&id_remapper, specifics)) {
           // Updating worked - there was a matching visit in the DB already.
-          // This happens during initial merge, or when an existing visit got
-          // untracked. Nothing further to be done here.
+          // Nothing further to be done here.
         } else {
           // Updating didn't work, so actually add the data instead.
           if (!AddEntityInBackend(&id_remapper, specifics)) {
-            // Something went wrong - stop tracking the entity.
+            // Something went wrong.
             RecordDatabaseError(
                 SyncHistoryDatabaseError::kApplySyncChangesAddSyncedVisit);
-            change_processor()->UntrackEntityForClientTagHash(
-                entity_change->data().client_tag_hash);
             break;
           }
         }
@@ -360,8 +366,13 @@
       }
       case syncer::EntityChange::ACTION_DELETE:
         // Deletes are not supported - they're handled via
-        // HISTORY_DELETE_DIRECTIVE instead.
-        DLOG(ERROR) << "Received unexpected deletion for HISTORY";
+        // HISTORY_DELETE_DIRECTIVE instead. And, since metadata isn't tracked,
+        // the processor should never send deletions anyway (even if a different
+        // client uploaded a tombstone). [Edge case: Metadata for unsynced
+        // entities *is* tracked, but then an incoming tombstone would result in
+        // a conflict that'd be resolved as "local edit wins over remote
+        // deletion", so still no ACTION_DELETE would arrive here.]
+        NOTREACHED();
         break;
     }
   }
@@ -542,7 +553,9 @@
   }
 
   // No need to send any actual deletions: A HistoryDeleteDirective will take
-  // care of that. Just untrack all entities and clear their metadata.
+  // care of that. Just untrack all entities and clear their metadata. (The only
+  // case where such metadata actually exists is if there are entities that are
+  // waiting for a commit. Clear their metadata, to cancel those commits.)
   auto metadata_batch = std::make_unique<syncer::MetadataBatch>();
   if (!sync_metadata_database_->GetAllSyncMetadata(metadata_batch.get())) {
     RecordDatabaseError(SyncHistoryDatabaseError::kOnURLsDeletedReadMetadata);
@@ -609,7 +622,8 @@
   // No need to send an actual deletion: Either this was an expiry, in which
   // no deletion should be sent, or if it's an actual deletion, then a
   // HistoryDeleteDirective will take care of that. Just untrack the entity and
-  // delete its metadata.
+  // delete its metadata (just in case this entity was waiting to be committed -
+  // otherwise no metadata exists anyway).
   std::string storage_key = GetStorageKeyFromVisitRow(visit_row);
   sync_metadata_database_->ClearSyncMetadata(syncer::HISTORY, storage_key);
   change_processor()->UntrackEntityForStorageKey(storage_key);
diff --git a/components/sync/driver/glue/sync_engine_impl.cc b/components/sync/driver/glue/sync_engine_impl.cc
index 03c85185..a30db38 100644
--- a/components/sync/driver/glue/sync_engine_impl.cc
+++ b/components/sync/driver/glue/sync_engine_impl.cc
@@ -622,6 +622,11 @@
   if (!sessions_invalidation_enabled_) {
     invalidation_enabled_types.Remove(syncer::SESSIONS);
   }
+#if BUILDFLAG(IS_ANDROID)
+  // On Android, don't subscribe to HISTORY invalidations, to save network
+  // traffic.
+  invalidation_enabled_types.Remove(HISTORY);
+#endif
   // kUseSyncInvalidations means that the new invalidations system is
   // used for all data types except Wallet and Offer, so only keep these types.
   if (base::FeatureList::IsEnabled(kSyncSendInterestedDataTypes) &&
diff --git a/components/sync/driver/sync_service_impl.cc b/components/sync/driver/sync_service_impl.cc
index 1dda54d..86679134 100644
--- a/components/sync/driver/sync_service_impl.cc
+++ b/components/sync/driver/sync_service_impl.cc
@@ -1256,6 +1256,11 @@
   if (!sessions_invalidations_enabled_) {
     types.Remove(SESSIONS);
   }
+#if BUILDFLAG(IS_ANDROID)
+  // On Android, don't subscribe to HISTORY invalidations, to save network
+  // traffic.
+  types.Remove(HISTORY);
+#endif
   if (!(base::FeatureList::IsEnabled(kUseSyncInvalidations) &&
         base::FeatureList::IsEnabled(kUseSyncInvalidationsForWalletAndOffer))) {
     types.RemoveAll({AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER});
diff --git a/components/sync/model/client_tag_based_remote_update_handler.cc b/components/sync/model/client_tag_based_remote_update_handler.cc
index 77cf4b69..8f78fb1e 100644
--- a/components/sync/model/client_tag_based_remote_update_handler.cc
+++ b/components/sync/model/client_tag_based_remote_update_handler.cc
@@ -149,7 +149,7 @@
     return nullptr;
   }
 
-  if (entity && entity->UpdateIsReflection(update.response_version)) {
+  if (entity && entity->IsVersionAlreadyKnown(update.response_version)) {
     // Seen this update before; just ignore it.
     return nullptr;
   }
diff --git a/components/sync/model/processor_entity.cc b/components/sync/model/processor_entity.cc
index 4ea02eb..0864eae 100644
--- a/components/sync/model/processor_entity.cc
+++ b/components/sync/model/processor_entity.cc
@@ -142,7 +142,7 @@
   return metadata_.is_deleted() && !IsUnsynced();
 }
 
-bool ProcessorEntity::UpdateIsReflection(int64_t update_version) const {
+bool ProcessorEntity::IsVersionAlreadyKnown(int64_t update_version) const {
   return metadata_.server_version() >= update_version;
 }
 
diff --git a/components/sync/model/processor_entity.h b/components/sync/model/processor_entity.h
index 1c38c0a..3064b191 100644
--- a/components/sync/model/processor_entity.h
+++ b/components/sync/model/processor_entity.h
@@ -68,12 +68,15 @@
   bool RequiresCommitData() const;
 
   // Whether it's safe to clear the metadata for this entity. This means that
-  // the entity is deleted and either knowledge of this entity has never left
-  // this client or it is up to date with the server.
+  // the entity is deleted and it is up to date with the server (i.e. is *not*
+  // unsynced).
   bool CanClearMetadata() const;
 
-  // Returns true if the specified update version does not contain new data.
-  bool UpdateIsReflection(int64_t update_version) const;
+  // Returns true if the specified `update_version` is already known, i.e. is
+  // small or equal to the last known server version.
+  // This is the case for reflections, but can also be true in some other edge
+  // cases (e.g. updates were received out of order).
+  bool IsVersionAlreadyKnown(int64_t update_version) const;
 
   // Records that an update from the server was received but ignores its data.
   void RecordIgnoredRemoteUpdate(const UpdateResponseData& response_data);
diff --git a/components/sync/model/processor_entity_unittest.cc b/components/sync/model/processor_entity_unittest.cc
index 9973d8b..ce66d13 100644
--- a/components/sync/model/processor_entity_unittest.cc
+++ b/components/sync/model/processor_entity_unittest.cc
@@ -156,7 +156,7 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_FALSE(entity->CanClearMetadata());
-  EXPECT_FALSE(entity->UpdateIsReflection(1));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
   EXPECT_FALSE(entity->HasCommitData());
 }
 
@@ -179,7 +179,7 @@
   EXPECT_TRUE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_FALSE(entity->CanClearMetadata());
-  EXPECT_FALSE(entity->UpdateIsReflection(1));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
   EXPECT_TRUE(entity->HasCommitData());
 
   EXPECT_EQ(kValue1, entity->commit_data().specifics.preference().value());
@@ -195,7 +195,7 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_FALSE(entity->CanClearMetadata());
-  EXPECT_FALSE(entity->UpdateIsReflection(1));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(1));
 
   const EntityData& data = *request.entity;
   EXPECT_EQ("", data.id);
@@ -228,7 +228,7 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_FALSE(entity->CanClearMetadata());
-  EXPECT_TRUE(entity->UpdateIsReflection(1));
+  EXPECT_TRUE(entity->IsVersionAlreadyKnown(1));
   EXPECT_FALSE(entity->HasCommitData());
 }
 
@@ -254,9 +254,9 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_FALSE(entity->CanClearMetadata());
-  EXPECT_TRUE(entity->UpdateIsReflection(9));
-  EXPECT_TRUE(entity->UpdateIsReflection(10));
-  EXPECT_FALSE(entity->UpdateIsReflection(11));
+  EXPECT_TRUE(entity->IsVersionAlreadyKnown(9));
+  EXPECT_TRUE(entity->IsVersionAlreadyKnown(10));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(11));
   EXPECT_FALSE(entity->HasCommitData());
 }
 
@@ -297,8 +297,8 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_TRUE(entity->CanClearMetadata());
-  EXPECT_TRUE(entity->UpdateIsReflection(1));
-  EXPECT_FALSE(entity->UpdateIsReflection(2));
+  EXPECT_TRUE(entity->IsVersionAlreadyKnown(1));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(2));
   EXPECT_FALSE(entity->HasCommitData());
 }
 
@@ -324,8 +324,8 @@
   EXPECT_FALSE(entity->RequiresCommitRequest());
   EXPECT_FALSE(entity->RequiresCommitData());
   EXPECT_TRUE(entity->CanClearMetadata());
-  EXPECT_TRUE(entity->UpdateIsReflection(2));
-  EXPECT_FALSE(entity->UpdateIsReflection(3));
+  EXPECT_TRUE(entity->IsVersionAlreadyKnown(2));
+  EXPECT_FALSE(entity->IsVersionAlreadyKnown(3));
   EXPECT_FALSE(entity->HasCommitData());
 }
 
diff --git a/components/sync/nigori/nigori_model_type_processor.cc b/components/sync/nigori/nigori_model_type_processor.cc
index 8fb08a5..8c660149 100644
--- a/components/sync/nigori/nigori_model_type_processor.cc
+++ b/components/sync/nigori/nigori_model_type_processor.cc
@@ -163,7 +163,7 @@
   // are adding the following DCHECK to simplify the code.
   DCHECK(!updates[0].entity.is_deleted());
 
-  if (entity_->UpdateIsReflection(updates[0].response_version)) {
+  if (entity_->IsVersionAlreadyKnown(updates[0].response_version)) {
     // Seen this update before; just ignore it.
     bridge_->ApplySyncChanges(/*data=*/absl::nullopt);
     return;
diff --git a/components/viz/test/test_gpu_memory_buffer_manager.cc b/components/viz/test/test_gpu_memory_buffer_manager.cc
index 5b643d1..20626b7 100644
--- a/components/viz/test/test_gpu_memory_buffer_manager.cc
+++ b/components/viz/test/test_gpu_memory_buffer_manager.cc
@@ -78,9 +78,6 @@
     handle.stride = base::checked_cast<int32_t>(stride_);
     return handle;
   }
-  ClientBuffer AsClientBuffer() override {
-    return reinterpret_cast<ClientBuffer>(this);
-  }
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
@@ -127,9 +124,6 @@
   gfx::GpuMemoryBufferHandle CloneHandle() const override {
     return client_buffer_->CloneHandle();
   }
-  ClientBuffer AsClientBuffer() override {
-    return client_buffer_->AsClientBuffer();
-  }
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/docs/testing/web_tests_in_content_shell.md b/docs/testing/web_tests_in_content_shell.md
index ebf30bf..6fc8d2a 100644
--- a/docs/testing/web_tests_in_content_shell.md
+++ b/docs/testing/web_tests_in_content_shell.md
@@ -101,7 +101,7 @@
 tests require some setup before running in Content Shell:
 
 ```bash
-vpython third_party/blink/tools/run_blink_wptserve.py -t <build directory>
+vpython3 third_party/blink/tools/run_blink_wptserve.py -t <build directory>
 ```
 
 Then run the test:
@@ -144,7 +144,7 @@
 start the server:
 
 ```bash
-vpython third_party/blink/tools/run_blink_wptserve.py
+vpython3 third_party/blink/tools/run_blink_wptserve.py
 ```
 
 Then start Content Shell with some additional flags:
diff --git a/google_apis/common/base_requests.cc b/google_apis/common/base_requests.cc
index 586f247..1a1565d 100644
--- a/google_apis/common/base_requests.cc
+++ b/google_apis/common/base_requests.cc
@@ -60,20 +60,19 @@
   const char kErrorCodeKey[] = "code";
 
   std::unique_ptr<const base::Value> value(google_apis::ParseJson(error_body));
-  const base::DictionaryValue* dictionary = nullptr;
-  const base::DictionaryValue* error = nullptr;
-  if (value && value->GetAsDictionary(&dictionary) &&
-      dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
+  const base::Value::Dict* dictionary = value ? value->GetIfDict() : nullptr;
+  const base::Value::Dict* error =
+      dictionary ? dictionary->FindDict(kErrorKey) : nullptr;
+  if (error) {
     // Get error message and code.
-    const std::string* message = error->FindStringKey(kErrorMessageKey);
-    absl::optional<int> code = error->FindIntKey(kErrorCodeKey);
+    const std::string* message = error->FindString(kErrorMessageKey);
+    absl::optional<int> code = error->FindInt(kErrorCodeKey);
     DLOG(ERROR) << "code: " << (code ? code.value() : OTHER_ERROR)
                 << ", message: " << (message ? *message : "");
 
     // Returns the reason of the first error.
-    const base::ListValue* errors = nullptr;
-    if (error->GetListWithoutPathExpansion(kErrorErrorsKey, &errors)) {
-      const base::Value& first_error = errors->GetListDeprecated()[0];
+    if (const base::Value::List* errors = error->FindList(kErrorErrorsKey)) {
+      const base::Value& first_error = (*errors)[0];
       if (first_error.is_dict()) {
         const std::string* reason = first_error.FindStringKey(kErrorReasonKey);
         if (reason)
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index ea1168d..4c803c70 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -72,10 +72,6 @@
                       gfx::BufferFormat format)
       : mapped_(false), bytes_(bytes), size_(size), format_(format) {}
 
-  static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer) {
-    return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
-  }
-
   // Overridden from gfx::GpuMemoryBuffer:
   bool Map() override {
     DCHECK(!mapped_);
@@ -109,9 +105,6 @@
     NOTREACHED();
     return gfx::GpuMemoryBufferHandle();
   }
-  ClientBuffer AsClientBuffer() override {
-    return reinterpret_cast<ClientBuffer>(this);
-  }
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
@@ -139,10 +132,6 @@
     CFRelease(iosurface_);
   }
 
-  static IOSurfaceGpuMemoryBuffer* FromClientBuffer(ClientBuffer buffer) {
-    return reinterpret_cast<IOSurfaceGpuMemoryBuffer*>(buffer);
-  }
-
   // Overridden from gfx::GpuMemoryBuffer:
   bool Map() override {
     DCHECK(!mapped_);
@@ -175,9 +164,6 @@
     NOTREACHED();
     return gfx::GpuMemoryBufferHandle();
   }
-  ClientBuffer AsClientBuffer() override {
-    return reinterpret_cast<ClientBuffer>(this);
-  }
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl.cc b/gpu/ipc/common/gpu_memory_buffer_impl.cc
index 6c25b7a..cec2d6c 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_impl.cc
@@ -38,10 +38,6 @@
   return id_;
 }
 
-ClientBuffer GpuMemoryBufferImpl::AsClientBuffer() {
-  return reinterpret_cast<ClientBuffer>(this);
-}
-
 void GpuMemoryBufferImpl::OnMemoryDump(
     base::trace_event::ProcessMemoryDump* pmd,
     const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl.h b/gpu/ipc/common/gpu_memory_buffer_impl.h
index 6a9f1ae..fb50de7 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl.h
@@ -30,7 +30,6 @@
   gfx::Size GetSize() const override;
   gfx::BufferFormat GetFormat() const override;
   gfx::GpuMemoryBufferId GetId() const override;
-  ClientBuffer AsClientBuffer() override;
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/infra/config/dev/subprojects/chromium/subproject.star b/infra/config/dev/subprojects/chromium/subproject.star
index 0000421..d79ebb0e 100644
--- a/infra/config/dev/subprojects/chromium/subproject.star
+++ b/infra/config/dev/subprojects/chromium/subproject.star
@@ -3,4 +3,5 @@
 # found in the LICENSE file.
 
 exec("./ci.star")
+exec("./try.star")
 exec("./consoles/chromium.swarm.star")
diff --git a/infra/config/dev/subprojects/chromium/try.star b/infra/config/dev/subprojects/chromium/try.star
new file mode 100644
index 0000000..7b3afd4
--- /dev/null
+++ b/infra/config/dev/subprojects/chromium/try.star
@@ -0,0 +1,16 @@
+# 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.
+
+# A realm for tryjob data.
+luci.realm(
+    name = "try",
+    bindings = [
+        luci.binding(
+            roles = "role/buildbucket.reader",
+            groups = "all",
+        ),
+        # Other roles are inherited from @root which grants them to group:all.
+    ],
+)
+
diff --git a/infra/config/generated/luci/realms-dev.cfg b/infra/config/generated/luci/realms-dev.cfg
index 9b81b53b..f73bd2e 100644
--- a/infra/config/generated/luci/realms-dev.cfg
+++ b/infra/config/generated/luci/realms-dev.cfg
@@ -110,3 +110,10 @@
     principals: "group:luci-resultdb-access"
   }
 }
+realms {
+  name: "try"
+  bindings {
+    role: "role/buildbucket.reader"
+    principals: "group:all"
+  }
+}
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index 019561b..0bf02f2 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -1239,6 +1239,12 @@
 }
 #endif  // !defined(NDEBUG)
 
+- (void)focusFakebox {
+  if ([self isNTPActiveForCurrentWebState]) {
+    [_ntpCoordinator focusFakebox];
+  }
+}
+
 #pragma mark - DefaultPromoCommands
 
 - (void)showTailoredPromoStaySafe {
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index a25cdcd8..6a398d1 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -3291,12 +3291,6 @@
   }
 }
 
-- (void)focusFakebox {
-  if (self.isNTPActiveForCurrentWebState) {
-    [self.ntpCoordinator focusFakebox];
-  }
-}
-
 #pragma mark - WebStateListObserving methods
 
 // TODO(crbug.com/1329088): Move BVC's tab lifeceyle event updates to a
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h
index c48712c..67dcccd 100644
--- a/ios/chrome/browser/ui/commands/browser_commands.h
+++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -31,10 +31,6 @@
 // Prepares the browser to display a popup menu.
 - (void)prepareForPopupMenuPresentation:(PopupMenuCommandType)type;
 
-// Animates the NTP fakebox to the focused position and focuses the real
-// omnibox.
-- (void)focusFakebox;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
index 1b5827b..ad263a0 100644
--- a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
+++ b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
@@ -83,6 +83,10 @@
 - (void)viewSource;
 #endif
 
+// Animates the NTP fakebox to the focused position and focuses the real
+// omnibox.
+- (void)focusFakebox;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COORDINATOR_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
index 43fd16c9..587bd6f 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/location_bar/location_bar_url_loader.h"
 #import "ios/chrome/browser/ui/omnibox/location_bar_delegate.h"
 
+@protocol BrowserCoordinatorCommands;
 @protocol EditViewAnimatee;
 @protocol LocationBarAnimatee;
 @protocol OmniboxPopupPresenterDelegate;
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index 999631d..f9df9a3 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -32,7 +32,7 @@
 #import "ios/chrome/browser/ui/badges/badge_delegate.h"
 #import "ios/chrome/browser/ui/badges/badge_mediator.h"
 #import "ios/chrome/browser/ui/badges/badge_view_controller.h"
-#include "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/load_query_commands.h"
 #import "ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.h"
@@ -161,8 +161,8 @@
   // TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol
   // clean up.
   self.viewController.dispatcher =
-      static_cast<id<ActivityServiceCommands, BrowserCommands,
-                     ApplicationCommands, LoadQueryCommands, OmniboxCommands>>(
+      static_cast<id<ActivityServiceCommands, ApplicationCommands,
+                     LoadQueryCommands, OmniboxCommands>>(
           self.browser->GetCommandDispatcher());
   self.viewController.voiceSearchEnabled =
       ios::provider::IsVoiceSearchEnabled();
@@ -359,7 +359,10 @@
   // before focusing the omnibox.
   if (IsVisibleURLNewTabPage([self webState]) &&
       !self.browserState->IsOffTheRecord()) {
-    [self.viewController.dispatcher focusFakebox];
+    id<BrowserCoordinatorCommands> browserCoordinatorCommandsHandler =
+        HandlerForProtocol(self.browser->GetCommandDispatcher(),
+                           BrowserCoordinatorCommands);
+    [browserCoordinatorCommandsHandler focusFakebox];
   } else {
     [self.omniboxCoordinator focusOmnibox];
   }
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
index c7f058a..5db2a72 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
@@ -16,7 +16,6 @@
 @class OmniboxTextFieldIOS;
 @protocol ActivityServiceCommands;
 @protocol ApplicationCommands;
-@protocol BrowserCommands;
 @protocol LocationBarOffsetProvider;
 @protocol LoadQueryCommands;
 
@@ -66,7 +65,6 @@
 // The dispatcher for the share button, voice search, and long press actions.
 @property(nonatomic, weak) id<ActivityServiceCommands,
                               ApplicationCommands,
-                              BrowserCommands,
                               LoadQueryCommands,
                               OmniboxCommands>
     dispatcher;
diff --git a/ios/web/web_state/ui/crw_web_request_controller.mm b/ios/web/web_state/ui/crw_web_request_controller.mm
index 541f36333..1e49cd0c 100644
--- a/ios/web/web_state/ui/crw_web_request_controller.mm
+++ b/ios/web/web_state/ui/crw_web_request_controller.mm
@@ -526,18 +526,17 @@
     // building iOS-related code.
 #if defined(__IPHONE_15_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_0
     if (@available(iOS 15, *)) {
+      [request.URL startAccessingSecurityScopedResource];
       navigation = [self.webView loadFileRequest:request
                          allowingReadAccessToURL:request.URL];
-    } else {
+      [request.URL stopAccessingSecurityScopedResource];
+    } else
+#endif
+    {
       NSURL* navigationNSURL = net::NSURLWithGURL(navigationURL);
       navigation = [self.webView loadFileURL:navigationNSURL
                      allowingReadAccessToURL:navigationNSURL];
     }
-#else
-    NSURL* navigationNSURL = net::NSURLWithGURL(navigationURL);
-    navigation = [self.webView loadFileURL:navigationNSURL
-                   allowingReadAccessToURL:navigationNSURL];
-#endif
   } else {
     navigation = [self.webView loadRequest:request];
   }
diff --git a/media/gpu/test/local_gpu_memory_buffer_manager.cc b/media/gpu/test/local_gpu_memory_buffer_manager.cc
index e8b4fa0..f7d2481f 100644
--- a/media/gpu/test/local_gpu_memory_buffer_manager.cc
+++ b/media/gpu/test/local_gpu_memory_buffer_manager.cc
@@ -203,10 +203,6 @@
     return handle;
   }
 
-  ClientBuffer AsClientBuffer() override {
-    return reinterpret_cast<ClientBuffer>(this);
-  }
-
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/media/video/fake_gpu_memory_buffer.cc b/media/video/fake_gpu_memory_buffer.cc
index f3e6c49..ed16744c 100644
--- a/media/video/fake_gpu_memory_buffer.cc
+++ b/media/video/fake_gpu_memory_buffer.cc
@@ -141,11 +141,6 @@
   return handle;
 }
 
-ClientBuffer FakeGpuMemoryBuffer::AsClientBuffer() {
-  NOTREACHED();
-  return ClientBuffer();
-}
-
 void FakeGpuMemoryBuffer::OnMemoryDump(
     base::trace_event::ProcessMemoryDump* pmd,
     const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/media/video/fake_gpu_memory_buffer.h b/media/video/fake_gpu_memory_buffer.h
index 0e706f13..1d27fb7 100644
--- a/media/video/fake_gpu_memory_buffer.h
+++ b/media/video/fake_gpu_memory_buffer.h
@@ -38,7 +38,6 @@
   gfx::GpuMemoryBufferId GetId() const override;
   gfx::GpuMemoryBufferType GetType() const override;
   gfx::GpuMemoryBufferHandle CloneHandle() const override;
-  ClientBuffer AsClientBuffer() override;
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/media/video/mock_gpu_video_accelerator_factories.cc b/media/video/mock_gpu_video_accelerator_factories.cc
index 88532ab..c8d9092 100644
--- a/media/video/mock_gpu_video_accelerator_factories.cc
+++ b/media/video/mock_gpu_video_accelerator_factories.cc
@@ -76,9 +76,6 @@
   gfx::GpuMemoryBufferHandle CloneHandle() const override {
     return gfx::GpuMemoryBufferHandle();
   }
-  ClientBuffer AsClientBuffer() override {
-    return reinterpret_cast<ClientBuffer>(this);
-  }
   void OnMemoryDump(
       base::trace_event::ProcessMemoryDump* pmd,
       const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 5e252fa..caff27b 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -362,8 +362,16 @@
   // must do so before any other threads try to access the API below, and it
   // must outlive all other threads which might try to use it.
   static std::unique_ptr<NetworkChangeNotifier> CreateIfNeeded(
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+      // TODO(crbug.com/1347382): Remove this section and align the behavior
+      // with other platforms or confirm that Lacros needs to be separated.
+      NetworkChangeNotifier::ConnectionType initial_type = CONNECTION_UNKNOWN,
+      NetworkChangeNotifier::ConnectionSubtype initial_subtype =
+          SUBTYPE_UNKNOWN);
+#else
       NetworkChangeNotifier::ConnectionType initial_type = CONNECTION_NONE,
       NetworkChangeNotifier::ConnectionSubtype initial_subtype = SUBTYPE_NONE);
+#endif
 
   // Returns the most likely cost attribute for the default network connection.
   // The value does not indicate with absolute certainty if using the connection
diff --git a/services/device/compute_pressure/core_times_unittest.cc b/services/device/compute_pressure/core_times_unittest.cc
index abba05aa..abc9c91 100644
--- a/services/device/compute_pressure/core_times_unittest.cc
+++ b/services/device/compute_pressure/core_times_unittest.cc
@@ -1,4 +1,3 @@
-
 // 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.
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn
index 24ecf19..d4eca55 100644
--- a/services/device/geolocation/BUILD.gn
+++ b/services/device/geolocation/BUILD.gn
@@ -44,8 +44,8 @@
     "wifi_data.h",
     "wifi_data_provider.cc",
     "wifi_data_provider.h",
-    "wifi_data_provider_manager.cc",
-    "wifi_data_provider_manager.h",
+    "wifi_data_provider_handle.cc",
+    "wifi_data_provider_handle.h",
     "wifi_polling_policy.cc",
     "wifi_polling_policy.h",
   ]
@@ -136,7 +136,7 @@
       "wifi_data_provider_win.h",
     ]
   } else {
-    # WifiDataProviderManager declares a static factory method that is defined
+    # WifiDataProviderHandle declares a static factory method that is defined
     # by the platform implementation. Platforms with no Wi-Fi data provider must
     # include EmptyWifiDataProvider to provide this definition.
     sources += [
diff --git a/services/device/geolocation/empty_wifi_data_provider.cc b/services/device/geolocation/empty_wifi_data_provider.cc
index 029afe0..ed143dd 100644
--- a/services/device/geolocation/empty_wifi_data_provider.cc
+++ b/services/device/geolocation/empty_wifi_data_provider.cc
@@ -4,7 +4,7 @@
 
 #include "services/device/geolocation/empty_wifi_data_provider.h"
 
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 
 namespace device {
 
@@ -26,7 +26,7 @@
 void EmptyWifiDataProvider::ForceRescan() {}
 
 // static
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new EmptyWifiDataProvider();
 }
 
diff --git a/services/device/geolocation/network_location_provider.cc b/services/device/geolocation/network_location_provider.cc
index 391d1fb..7541c35 100644
--- a/services/device/geolocation/network_location_provider.cc
+++ b/services/device/geolocation/network_location_provider.cc
@@ -44,8 +44,7 @@
     const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     const std::string& api_key,
     PositionCache* position_cache)
-    : wifi_data_provider_manager_(nullptr),
-      wifi_data_update_callback_(
+    : wifi_data_update_callback_(
           base::BindRepeating(&NetworkLocationProvider::OnWifiDataUpdate,
                               base::Unretained(this))),
       is_wifi_data_complete_(false),
@@ -109,7 +108,7 @@
     location_provider_update_callback_.Run(this, error_position);
   }
   if (!was_permission_granted && is_system_permission_granted_ && IsStarted()) {
-    wifi_data_provider_manager_->ForceRescan();
+    wifi_data_provider_handle_->ForceRescan();
     OnWifiDataUpdate();
   }
 }
@@ -130,7 +129,7 @@
     return;
   }
 #endif
-  is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_);
+  is_wifi_data_complete_ = wifi_data_provider_handle_->GetData(&wifi_data_);
   if (is_wifi_data_complete_) {
     wifi_timestamp_ = base::Time::Now();
     is_new_data_available_ = true;
@@ -149,7 +148,7 @@
   // data changes, but is on the order of a few seconds to several minutes.
   // In this case it is better to call RequestPosition and return a cached
   // position estimate if it is available.
-  bool delayed = wifi_data_provider_manager_->DelayedByPolicy();
+  bool delayed = wifi_data_provider_handle_->DelayedByPolicy();
   if (is_wifi_data_complete_ || delayed)
     RequestPosition();
 }
@@ -176,10 +175,10 @@
   if (IsStarted())
     return;
 
-  // Registers a callback with the data provider. The first call to Register()
-  // will create a singleton data provider that will be deleted on Unregister().
-  wifi_data_provider_manager_ =
-      WifiDataProviderManager::Register(&wifi_data_update_callback_);
+  // Registers a callback with the data provider.
+  // Releasing the handle will automatically unregister the callback.
+  wifi_data_provider_handle_ =
+      WifiDataProviderHandle::CreateHandle(&wifi_data_update_callback_);
 
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
@@ -193,8 +192,7 @@
 void NetworkLocationProvider::StopProvider() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(IsStarted());
-  wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_);
-  wifi_data_provider_manager_ = nullptr;
+  wifi_data_provider_handle_ = nullptr;
   weak_factory_.InvalidateWeakPtrs();
 }
 
@@ -301,7 +299,7 @@
 }
 
 bool NetworkLocationProvider::IsStarted() const {
-  return wifi_data_provider_manager_ != nullptr;
+  return wifi_data_provider_handle_ != nullptr;
 }
 
 }  // namespace device
diff --git a/services/device/geolocation/network_location_provider.h b/services/device/geolocation/network_location_provider.h
index fc94d5f..d45975b 100644
--- a/services/device/geolocation/network_location_provider.h
+++ b/services/device/geolocation/network_location_provider.h
@@ -20,7 +20,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "services/device/geolocation/network_location_request.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 #include "services/device/public/cpp/geolocation/geolocation_manager.h"
 #include "services/device/public/cpp/geolocation/location_provider.h"
 #include "services/device/public/mojom/geoposition.mojom.h"
@@ -58,7 +58,7 @@
   void RequestPosition();
 
   // Gets called when new wifi data is available, either via explicit request to
-  // or callback from |wifi_data_provider_manager_|.
+  // or callback from |wifi_data_provider_handle_|.
   void OnWifiDataUpdate();
 
   bool IsStarted() const;
@@ -69,10 +69,9 @@
 
   // The wifi data provider, acquired via global factories. Valid between
   // StartProvider() and StopProvider(), and checked via IsStarted().
-  raw_ptr<WifiDataProviderManager, DanglingUntriaged>
-      wifi_data_provider_manager_;
+  std::unique_ptr<WifiDataProviderHandle> wifi_data_provider_handle_;
 
-  WifiDataProviderManager::WifiDataUpdateCallback wifi_data_update_callback_;
+  WifiDataProviderHandle::WifiDataUpdateCallback wifi_data_update_callback_;
 
 #if BUILDFLAG(IS_MAC)
   // Used to keep track of macOS System Permission changes. Also, ensures
diff --git a/services/device/geolocation/network_location_provider_unittest.cc b/services/device/geolocation/network_location_provider_unittest.cc
index 3c102053..0120354 100644
--- a/services/device/geolocation/network_location_provider_unittest.cc
+++ b/services/device/geolocation/network_location_provider_unittest.cc
@@ -131,7 +131,7 @@
 class GeolocationNetworkProviderTest : public testing::Test {
  public:
   void TearDown() override {
-    WifiDataProviderManager::ResetFactoryForTesting();
+    WifiDataProviderHandle::ResetFactoryForTesting();
     grant_system_permission_by_default_ = true;
   }
 
@@ -173,7 +173,7 @@
       : wifi_data_provider_(MockWifiDataProvider::CreateInstance()) {
     // TODO(joth): Really these should be in SetUp, not here, but they take no
     // effect on Mac OS Release builds if done there. I kid not. Figure out why.
-    WifiDataProviderManager::SetFactoryForTesting(
+    WifiDataProviderHandle::SetFactoryForTesting(
         MockWifiDataProvider::GetInstance);
   }
 
diff --git a/services/device/geolocation/wifi_data_provider.h b/services/device/geolocation/wifi_data_provider.h
index 2af90a6..b195d27 100644
--- a/services/device/geolocation/wifi_data_provider.h
+++ b/services/device/geolocation/wifi_data_provider.h
@@ -9,6 +9,7 @@
 
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/task/single_thread_task_runner.h"
 #include "services/device/geolocation/wifi_data.h"
 
@@ -47,6 +48,10 @@
 
   bool has_callbacks() const;
 
+  base::WeakPtr<WifiDataProvider> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
  protected:
   friend class base::RefCountedThreadSafe<WifiDataProvider>;
   virtual ~WifiDataProvider();
@@ -70,6 +75,8 @@
   scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
 
   CallbackSet callbacks_;
+
+  base::WeakPtrFactory<WifiDataProvider> weak_factory_{this};
 };
 
 }  // namespace device
diff --git a/services/device/geolocation/wifi_data_provider_chromeos.cc b/services/device/geolocation/wifi_data_provider_chromeos.cc
index 94bfe14..76a6650 100644
--- a/services/device/geolocation/wifi_data_provider_chromeos.cc
+++ b/services/device/geolocation/wifi_data_provider_chromeos.cc
@@ -13,7 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/ash/components/network/geolocation_handler.h"
 #include "chromeos/ash/components/network/network_handler.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 
 using chromeos::NetworkHandler;
 
@@ -186,7 +186,7 @@
 }
 
 // static
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new WifiDataProviderChromeOs();
 }
 
diff --git a/services/device/geolocation/wifi_data_provider_common_unittest.cc b/services/device/geolocation/wifi_data_provider_common_unittest.cc
index d721b48d..922908840 100644
--- a/services/device/geolocation/wifi_data_provider_common_unittest.cc
+++ b/services/device/geolocation/wifi_data_provider_common_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -132,7 +132,7 @@
 
  protected:
   const base::test::SingleThreadTaskEnvironment task_environment_;
-  WifiDataProviderManager::WifiDataUpdateCallback wifi_data_callback_;
+  WifiDataProviderHandle::WifiDataUpdateCallback wifi_data_callback_;
   scoped_refptr<WifiDataProviderCommonWithMock> provider_;
 
   raw_ptr<MockWlanApi> wlan_api_ = nullptr;
diff --git a/services/device/geolocation/wifi_data_provider_handle.cc b/services/device/geolocation/wifi_data_provider_handle.cc
new file mode 100644
index 0000000..7548390
--- /dev/null
+++ b/services/device/geolocation/wifi_data_provider_handle.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 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 "services/device/geolocation/wifi_data_provider_handle.h"
+#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
+
+#include "services/device/geolocation/wifi_data_provider.h"
+
+namespace device {
+
+// static
+WifiDataProviderHandle::ImplFactoryFunction
+    WifiDataProviderHandle::factory_function_ = DefaultFactoryFunction;
+
+// static
+void WifiDataProviderHandle::SetFactoryForTesting(
+    ImplFactoryFunction factory_function_in) {
+  factory_function_ = factory_function_in;
+}
+
+// static
+scoped_refptr<WifiDataProvider> WifiDataProviderHandle::GetOrCreateProvider() {
+  static base::NoDestructor<base::WeakPtr<WifiDataProvider>> provider_;
+
+  scoped_refptr<WifiDataProvider> result = provider_.get()->get();
+  if (!result) {
+    DCHECK(factory_function_);
+    result = (*factory_function_)();
+    *provider_.get() = result->GetWeakPtr();
+  }
+
+  return result;
+}
+
+// static
+void WifiDataProviderHandle::ResetFactoryForTesting() {
+  factory_function_ = DefaultFactoryFunction;
+}
+
+std::unique_ptr<WifiDataProviderHandle> WifiDataProviderHandle::CreateHandle(
+    WifiDataUpdateCallback* callback) {
+  return base::WrapUnique(new WifiDataProviderHandle(callback));
+}
+
+WifiDataProviderHandle::WifiDataProviderHandle(WifiDataUpdateCallback* callback)
+    : impl_(GetOrCreateProvider()), callback_(callback) {
+  bool need_to_start_provider = !has_callbacks();
+  AddCallback(callback);
+  if (need_to_start_provider) {
+    StartDataProvider();
+  }
+}
+
+WifiDataProviderHandle::~WifiDataProviderHandle() {
+  bool removed = RemoveCallback(callback_);
+  DCHECK(removed);
+  if (!has_callbacks()) {
+    StopDataProvider();
+  }
+}
+
+bool WifiDataProviderHandle::DelayedByPolicy() {
+  return impl_->DelayedByPolicy();
+}
+
+bool WifiDataProviderHandle::GetData(WifiData* data) {
+  return impl_->GetData(data);
+}
+
+void WifiDataProviderHandle::ForceRescan() {
+  impl_->ForceRescan();
+}
+
+void WifiDataProviderHandle::AddCallback(WifiDataUpdateCallback* callback) {
+  impl_->AddCallback(callback);
+}
+
+bool WifiDataProviderHandle::RemoveCallback(WifiDataUpdateCallback* callback) {
+  return impl_->RemoveCallback(callback);
+}
+
+bool WifiDataProviderHandle::has_callbacks() const {
+  return impl_->has_callbacks();
+}
+
+void WifiDataProviderHandle::StartDataProvider() {
+  impl_->StartDataProvider();
+}
+
+void WifiDataProviderHandle::StopDataProvider() {
+  impl_->StopDataProvider();
+}
+
+}  // namespace device
diff --git a/services/device/geolocation/wifi_data_provider_handle.h b/services/device/geolocation/wifi_data_provider_handle.h
new file mode 100644
index 0000000..d9ce298
--- /dev/null
+++ b/services/device/geolocation/wifi_data_provider_handle.h
@@ -0,0 +1,88 @@
+// Copyright 2014 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.
+
+// A wifi data provider provides wifi data from the device that is used by a
+// NetworkLocationProvider to obtain a position fix. We use a singleton
+// instance of the wifi data provider manager, which is used by multiple
+// NetworkLocationProvider objects.
+//
+// This file provides WifiDataProviderHandle, which provides static methods to
+// access the singleton instance. The singleton instance uses a private
+// implementation of WifiDataProvider to abstract across platforms and also to
+// allow mock providers to be used for testing.
+
+#ifndef SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_HANDLE_H_
+#define SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_HANDLE_H_
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_util.h"
+#include "services/device/geolocation/wifi_data.h"
+
+namespace device {
+
+class WifiDataProvider;
+
+// A handle for using wifi data providers.
+//
+// We use a singleton instance of WifiDataProvider which is shared by multiple
+// network location providers.
+class WifiDataProviderHandle {
+ public:
+  typedef WifiDataProvider* (*ImplFactoryFunction)();
+  typedef base::RepeatingClosure WifiDataUpdateCallback;
+
+  // Sets the factory function which will be used by Register to create the
+  // implementation used by the singleton instance. This factory approach is
+  // used both to abstract across platform-specific implementations and to
+  // inject mock implementations for testing.
+  static void SetFactoryForTesting(ImplFactoryFunction factory_function_in);
+
+  // Resets the factory function to the default.
+  static void ResetFactoryForTesting();
+
+  // Creates a handle on WifiDataProvider.
+  static std::unique_ptr<WifiDataProviderHandle> CreateHandle(
+      WifiDataUpdateCallback* callback);
+
+  ~WifiDataProviderHandle();
+
+  WifiDataProviderHandle(const WifiDataProviderHandle&) = delete;
+  WifiDataProviderHandle& operator=(const WifiDataProviderHandle&) = delete;
+
+  // Returns true if the data provider is currently delayed by polling policy.
+  bool DelayedByPolicy();
+
+  // Provides whatever data the provider has, which may be nothing. Return
+  // value indicates whether this is all the data the provider could ever
+  // obtain.
+  bool GetData(WifiData* data);
+
+  void ForceRescan();
+
+ private:
+  explicit WifiDataProviderHandle(WifiDataUpdateCallback* callback);
+
+  void AddCallback(WifiDataUpdateCallback* callback);
+  bool RemoveCallback(WifiDataUpdateCallback* callback);
+  bool has_callbacks() const;
+
+  void StartDataProvider();
+  void StopDataProvider();
+
+  static WifiDataProvider* DefaultFactoryFunction();
+
+  static scoped_refptr<WifiDataProvider> GetOrCreateProvider();
+
+  // The factory function used to create the singleton instance.
+  static ImplFactoryFunction factory_function_;
+
+  scoped_refptr<WifiDataProvider> impl_;
+  WifiDataUpdateCallback* callback_;
+};
+
+}  // namespace device
+
+#endif  // SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_HANDLE_H_
diff --git a/services/device/geolocation/wifi_data_provider_lacros.cc b/services/device/geolocation/wifi_data_provider_lacros.cc
index bb78e33..3305c29 100644
--- a/services/device/geolocation/wifi_data_provider_lacros.cc
+++ b/services/device/geolocation/wifi_data_provider_lacros.cc
@@ -9,7 +9,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chromeos/lacros/lacros_service.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 #include "services/device/geolocation/wifi_polling_policy.h"
 
 namespace device {
@@ -180,7 +180,7 @@
 }
 
 // static
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new WifiDataProviderLacros();
 }
 
diff --git a/services/device/geolocation/wifi_data_provider_linux.cc b/services/device/geolocation/wifi_data_provider_linux.cc
index 8c0a26c..dfc9048 100644
--- a/services/device/geolocation/wifi_data_provider_linux.cc
+++ b/services/device/geolocation/wifi_data_provider_linux.cc
@@ -24,7 +24,7 @@
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "dbus/object_proxy.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 
 namespace device {
 namespace {
@@ -341,7 +341,7 @@
 }  // namespace
 
 // static
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new WifiDataProviderLinux();
 }
 
diff --git a/services/device/geolocation/wifi_data_provider_mac.mm b/services/device/geolocation/wifi_data_provider_mac.mm
index 028c805a..784802d 100644
--- a/services/device/geolocation/wifi_data_provider_mac.mm
+++ b/services/device/geolocation/wifi_data_provider_mac.mm
@@ -12,7 +12,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "services/device/geolocation/wifi_data_provider_common.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 
 namespace device {
 
@@ -90,7 +90,7 @@
 }  // namespace
 
 // static
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new WifiDataProviderMac();
 }
 
diff --git a/services/device/geolocation/wifi_data_provider_manager.cc b/services/device/geolocation/wifi_data_provider_manager.cc
deleted file mode 100644
index 67c6018..0000000
--- a/services/device/geolocation/wifi_data_provider_manager.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 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 "services/device/geolocation/wifi_data_provider_manager.h"
-
-#include "services/device/geolocation/wifi_data_provider.h"
-
-namespace device {
-
-// static
-WifiDataProviderManager* WifiDataProviderManager::instance_ = NULL;
-
-// static
-WifiDataProviderManager::ImplFactoryFunction
-    WifiDataProviderManager::factory_function_ = DefaultFactoryFunction;
-
-// static
-void WifiDataProviderManager::SetFactoryForTesting(
-    ImplFactoryFunction factory_function_in) {
-  factory_function_ = factory_function_in;
-}
-
-// static
-void WifiDataProviderManager::ResetFactoryForTesting() {
-  factory_function_ = DefaultFactoryFunction;
-}
-
-// static
-WifiDataProviderManager* WifiDataProviderManager::Register(
-    WifiDataUpdateCallback* callback) {
-  bool need_to_start_data_provider = false;
-  if (!instance_) {
-    instance_ = new WifiDataProviderManager();
-    need_to_start_data_provider = true;
-  }
-  DCHECK(instance_);
-  instance_->AddCallback(callback);
-  // Start the provider after adding the callback, to avoid any race in
-  // it running early.
-  if (need_to_start_data_provider)
-    instance_->StartDataProvider();
-  return instance_;
-}
-
-// static
-bool WifiDataProviderManager::Unregister(WifiDataUpdateCallback* callback) {
-  DCHECK(instance_);
-  DCHECK(instance_->has_callbacks());
-  if (!instance_->RemoveCallback(callback)) {
-    return false;
-  }
-  if (!instance_->has_callbacks()) {
-    // Must stop the data provider (and any implementation threads) before
-    // destroying to avoid any race conditions in access to the provider in
-    // the destructor chain.
-    instance_->StopDataProvider();
-    delete instance_;
-    instance_ = NULL;
-  }
-  return true;
-}
-
-WifiDataProviderManager::WifiDataProviderManager() {
-  DCHECK(factory_function_);
-  impl_ = (*factory_function_)();
-  DCHECK(impl_.get());
-}
-
-WifiDataProviderManager::~WifiDataProviderManager() {
-  DCHECK(impl_.get());
-}
-
-bool WifiDataProviderManager::DelayedByPolicy() {
-  return impl_->DelayedByPolicy();
-}
-
-bool WifiDataProviderManager::GetData(WifiData* data) {
-  return impl_->GetData(data);
-}
-
-void WifiDataProviderManager::ForceRescan() {
-  impl_->ForceRescan();
-}
-
-void WifiDataProviderManager::AddCallback(WifiDataUpdateCallback* callback) {
-  impl_->AddCallback(callback);
-}
-
-bool WifiDataProviderManager::RemoveCallback(WifiDataUpdateCallback* callback) {
-  return impl_->RemoveCallback(callback);
-}
-
-bool WifiDataProviderManager::has_callbacks() const {
-  return impl_->has_callbacks();
-}
-
-void WifiDataProviderManager::StartDataProvider() {
-  impl_->StartDataProvider();
-}
-
-void WifiDataProviderManager::StopDataProvider() {
-  impl_->StopDataProvider();
-}
-
-}  // namespace device
diff --git a/services/device/geolocation/wifi_data_provider_manager.h b/services/device/geolocation/wifi_data_provider_manager.h
deleted file mode 100644
index 5dd7cf1..0000000
--- a/services/device/geolocation/wifi_data_provider_manager.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2014 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.
-
-// A wifi data provider provides wifi data from the device that is used by a
-// NetworkLocationProvider to obtain a position fix. We use a singleton
-// instance of the wifi data provider manager, which is used by multiple
-// NetworkLocationProvider objects.
-//
-// This file provides WifiDataProviderManager, which provides static methods to
-// access the singleton instance. The singleton instance uses a private
-// implementation of WifiDataProvider to abstract across platforms and also to
-// allow mock providers to be used for testing.
-
-#ifndef SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
-#define SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_util.h"
-#include "services/device/geolocation/wifi_data.h"
-
-namespace device {
-
-class WifiDataProvider;
-
-// A manager for wifi data providers.
-//
-// We use a singleton instance of this class which is shared by multiple network
-// location providers. These location providers access the instance through the
-// Register and Unregister methods.
-class WifiDataProviderManager {
- public:
-  typedef WifiDataProvider* (*ImplFactoryFunction)(void);
-
-  // Sets the factory function which will be used by Register to create the
-  // implementation used by the singleton instance. This factory approach is
-  // used both to abstract accross platform-specific implementations and to
-  // inject mock implementations for testing.
-  static void SetFactoryForTesting(ImplFactoryFunction factory_function_in);
-
-  // Resets the factory function to the default.
-  static void ResetFactoryForTesting();
-
-  typedef base::RepeatingClosure WifiDataUpdateCallback;
-
-  // Registers a callback, which will be run whenever new data is available.
-  // Instantiates the singleton if necessary, and always returns it.
-  static WifiDataProviderManager* Register(WifiDataUpdateCallback* callback);
-
-  WifiDataProviderManager(const WifiDataProviderManager&) = delete;
-  WifiDataProviderManager& operator=(const WifiDataProviderManager&) = delete;
-
-  // Removes a callback. If this is the last callback, deletes the singleton
-  // instance. Return value indicates success.
-  static bool Unregister(WifiDataUpdateCallback* callback);
-
-  // Returns true if the data provider is currently delayed by polling policy.
-  bool DelayedByPolicy();
-
-  // Provides whatever data the provider has, which may be nothing. Return
-  // value indicates whether this is all the data the provider could ever
-  // obtain.
-  bool GetData(WifiData* data);
-
-  void ForceRescan();
-
- private:
-  // Private constructor and destructor, callers access singleton through
-  // Register and Unregister.
-  WifiDataProviderManager();
-  ~WifiDataProviderManager();
-
-  void AddCallback(WifiDataUpdateCallback* callback);
-  bool RemoveCallback(WifiDataUpdateCallback* callback);
-  bool has_callbacks() const;
-
-  void StartDataProvider();
-  void StopDataProvider();
-
-  static WifiDataProvider* DefaultFactoryFunction();
-
-  // The singleton-like instance of this class. (Not 'true' singleton, as it
-  // may go through multiple create/destroy/create cycles per process instance,
-  // e.g. when under test).
-  static WifiDataProviderManager* instance_;
-
-  // The factory function used to create the singleton instance.
-  static ImplFactoryFunction factory_function_;
-
-  // The internal implementation.
-  scoped_refptr<WifiDataProvider> impl_;
-};
-
-}  // namespace device
-
-#endif  // SERVICES_DEVICE_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
diff --git a/services/device/geolocation/wifi_data_provider_win.cc b/services/device/geolocation/wifi_data_provider_win.cc
index 036919d8c..4b8ae6e 100644
--- a/services/device/geolocation/wifi_data_provider_win.cc
+++ b/services/device/geolocation/wifi_data_provider_win.cc
@@ -16,7 +16,7 @@
 #include "base/win/windows_version.h"
 #include "services/device/geolocation/wifi_data_provider_common.h"
 #include "services/device/geolocation/wifi_data_provider_common_win.h"
-#include "services/device/geolocation/wifi_data_provider_manager.h"
+#include "services/device/geolocation/wifi_data_provider_handle.h"
 
 namespace device {
 
@@ -215,7 +215,7 @@
 
 }  // anonymous namespace
 
-WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderHandle::DefaultFactoryFunction() {
   return new WifiDataProviderWin();
 }
 
diff --git a/services/network/web_bundle/web_bundle_manager.cc b/services/network/web_bundle/web_bundle_manager.cc
index 09dfba95..17826aec 100644
--- a/services/network/web_bundle/web_bundle_manager.cc
+++ b/services/network/web_bundle/web_bundle_manager.cc
@@ -91,8 +91,10 @@
     absl::optional<std::string> devtools_request_id,
     const CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
     mojom::CrossOriginEmbedderPolicyReporter* coep_reporter) {
-  DCHECK(factories_.find({process_id, web_bundle_token_params.token}) ==
-         factories_.end());
+  Key key = GetKey(web_bundle_token_params, process_id);
+  DCHECK(factories_.find(key) == factories_.end());
+  DCHECK(web_bundle_token_params.handle.is_valid());
+  DCHECK_NE(process_id, mojom::kBrowserProcessId);
 
   mojo::Remote<mojom::WebBundleHandle> remote(
       web_bundle_token_params.CloneHandle());
@@ -100,10 +102,10 @@
   // Set a disconnect handler to remove a WebBundleURLLoaderFactory from this
   // WebBundleManager when the corresponding endpoint in the renderer is
   // removed.
-  remote.set_disconnect_handler(base::BindOnce(
-      &WebBundleManager::DisconnectHandler,
-      // |this| outlives |remote|.
-      base::Unretained(this), web_bundle_token_params.token, process_id));
+  remote.set_disconnect_handler(
+      base::BindOnce(&WebBundleManager::DisconnectHandler,
+                     // |this| outlives |remote|.
+                     base::Unretained(this), key));
 
   auto factory = std::make_unique<WebBundleURLLoaderFactory>(
       bundle_url, web_bundle_token_params, std::move(remote),
@@ -114,7 +116,7 @@
 
   // Process pending subresource requests if there are.
   // These subresource requests arrived earlier than the request for the bundle.
-  auto it = pending_requests_.find({process_id, web_bundle_token_params.token});
+  auto it = pending_requests_.find(key);
   if (it != pending_requests_.end()) {
     for (auto& pending_request : it->second) {
       factory->StartSubresourceRequest(
@@ -128,14 +130,12 @@
   }
 
   auto weak_factory = factory->GetWeakPtr();
-  factories_.insert({std::make_pair(process_id, web_bundle_token_params.token),
-                     std::move(factory)});
+  factories_.insert({key, std::move(factory)});
 
   return weak_factory;
 }
 
-base::WeakPtr<WebBundleURLLoaderFactory>
-WebBundleManager::GetWebBundleURLLoaderFactory(
+WebBundleManager::Key WebBundleManager::GetKey(
     const ResourceRequest::WebBundleTokenParams& token_params,
     int32_t process_id) {
   // If the request is from the browser process, use
@@ -143,7 +143,12 @@
   if (process_id == mojom::kBrowserProcessId)
     process_id = token_params.render_process_id;
 
-  auto it = factories_.find({process_id, token_params.token});
+  return {process_id, token_params.token};
+}
+
+base::WeakPtr<WebBundleURLLoaderFactory>
+WebBundleManager::GetWebBundleURLLoaderFactory(const Key& key) {
+  auto it = factories_.find(key);
   if (it == factories_.end()) {
     return nullptr;
   }
@@ -157,9 +162,11 @@
     int32_t process_id,
     mojo::Remote<mojom::TrustedHeaderClient> trusted_header_client) {
   DCHECK(url_request.web_bundle_token_params.has_value());
+  DCHECK(!url_request.web_bundle_token_params->handle.is_valid());
+
+  Key key = GetKey(*url_request.web_bundle_token_params, process_id);
   base::WeakPtr<WebBundleURLLoaderFactory> web_bundle_url_loader_factory =
-      GetWebBundleURLLoaderFactory(*url_request.web_bundle_token_params,
-                                   process_id);
+      GetWebBundleURLLoaderFactory(key);
   base::Time request_start_time = base::Time::Now();
   base::TimeTicks request_start_time_ticks = base::TimeTicks::Now();
   if (web_bundle_url_loader_factory) {
@@ -169,19 +176,18 @@
         request_start_time_ticks);
     return;
   }
+
   // A request for subresource arrives earlier than a request for a webbundle.
-  pending_requests_[{process_id, url_request.web_bundle_token_params->token}]
-      .push_back(std::make_unique<WebBundlePendingSubresourceRequest>(
+  pending_requests_[key].push_back(
+      std::make_unique<WebBundlePendingSubresourceRequest>(
           std::move(receiver), url_request, std::move(client),
           std::move(trusted_header_client), request_start_time,
           request_start_time_ticks));
 }
 
-void WebBundleManager::DisconnectHandler(
-    base::UnguessableToken web_bundle_token,
-    int32_t process_id) {
-  factories_.erase({process_id, web_bundle_token});
-  pending_requests_.erase({process_id, web_bundle_token});
+void WebBundleManager::DisconnectHandler(Key key) {
+  factories_.erase(key);
+  pending_requests_.erase(key);
 }
 
 bool WebBundleManager::AllocateMemoryForProcess(int32_t process_id,
diff --git a/services/network/web_bundle/web_bundle_manager.h b/services/network/web_bundle/web_bundle_manager.h
index 9a3d148c..aa1f5bb 100644
--- a/services/network/web_bundle/web_bundle_manager.h
+++ b/services/network/web_bundle/web_bundle_manager.h
@@ -57,11 +57,12 @@
   // Key is a tuple of (Process id, WebBundle token)
   using Key = std::pair<int32_t, base::UnguessableToken>;
 
+  static Key GetKey(const ResourceRequest::WebBundleTokenParams& token_params,
+                    int32_t process_id);
   base::WeakPtr<WebBundleURLLoaderFactory> GetWebBundleURLLoaderFactory(
-      const ResourceRequest::WebBundleTokenParams& params,
-      int32_t process_id);
+      const Key& key);
 
-  void DisconnectHandler(base::UnguessableToken token, int32_t process_id);
+  void DisconnectHandler(Key key);
 
   bool AllocateMemoryForProcess(int32_t process_id, uint64_t num_bytes);
   void ReleaseMemoryForProcess(int32_t process_id, uint64_t num_bytes);
diff --git a/services/network/web_bundle/web_bundle_manager_unittest.cc b/services/network/web_bundle/web_bundle_manager_unittest.cc
index d0c5400..ae9dd53 100644
--- a/services/network/web_bundle/web_bundle_manager_unittest.cc
+++ b/services/network/web_bundle/web_bundle_manager_unittest.cc
@@ -150,7 +150,8 @@
       WebBundleManager& manager,
       const ResourceRequest::WebBundleTokenParams& params,
       int32_t process_id) {
-    return manager.GetWebBundleURLLoaderFactory(params, process_id);
+    return manager.GetWebBundleURLLoaderFactory(
+        manager.GetKey(params, process_id));
   }
 
  private:
@@ -268,22 +269,36 @@
 
   WebBundleManager manager;
 
-  // Simulate that a subresource request arrives at first,
-  // calling WebBundleManager::StartSubresourceRequest.
+  // Simulate that two subresource requests arrives at first, one directly from
+  // a renderer and one through the browser, calling
+  // WebBundleManager::StartSubresourceRequest.
   base::UnguessableToken token = base::UnguessableToken::Create();
-  network::ResourceRequest request;
-  request.url = GURL(kResourceUrl);
-  request.method = "GET";
-  request.request_initiator = url::Origin::Create(GURL(kInitiatorUrl));
-  request.web_bundle_token_params = ResourceRequest::WebBundleTokenParams(
-      GURL(kBundleUrl), token, mojom::kInvalidProcessId);
 
-  mojo::Remote<network::mojom::URLLoader> loader;
-  auto client = std::make_unique<network::TestURLLoaderClient>();
+  struct TestRequest {
+    int32_t request_process_id;
+    int32_t token_params_process_id;
+    mojo::Remote<network::mojom::URLLoader> loader;
+    std::unique_ptr<network::TestURLLoaderClient> client;
+  } test_requests[] = {
+      {process_id1, mojom::kInvalidProcessId},
+      {mojom::kBrowserProcessId, process_id1},
+  };
 
-  manager.StartSubresourceRequest(loader.BindNewPipeAndPassReceiver(), request,
-                                  client->CreateRemote(), process_id1,
-                                  mojo::Remote<mojom::TrustedHeaderClient>());
+  for (TestRequest& req : test_requests) {
+    network::ResourceRequest request;
+    request.url = GURL(kResourceUrl);
+    request.method = "GET";
+    request.request_initiator = url::Origin::Create(GURL(kInitiatorUrl));
+    request.web_bundle_token_params = ResourceRequest::WebBundleTokenParams(
+        GURL(kBundleUrl), token, req.token_params_process_id);
+
+    req.client = std::make_unique<network::TestURLLoaderClient>();
+
+    manager.StartSubresourceRequest(req.loader.BindNewPipeAndPassReceiver(),
+                                    request, req.client->CreateRemote(),
+                                    req.request_process_id,
+                                    mojo::Remote<mojom::TrustedHeaderClient>());
+  }
 
   // Simulate that a webbundle request arrives, calling
   // WebBundleManager::CreateWebBundleURLLoaderFactory.
@@ -311,15 +326,17 @@
 
   producer.reset();
 
-  client->RunUntilComplete();
+  // Confirm that subresources are correctly loaded.
+  for (const TestRequest& req : test_requests) {
+    req.client->RunUntilComplete();
 
-  // Confirm that a subresource is correctly loaded.
-  EXPECT_EQ(net::OK, client->completion_status().error_code);
-  EXPECT_EQ(client->response_head()->web_bundle_url, GURL(kBundleUrl));
-  std::string body;
-  EXPECT_TRUE(
-      mojo::BlockingCopyToString(client->response_body_release(), &body));
-  EXPECT_EQ("body", body);
+    EXPECT_EQ(net::OK, req.client->completion_status().error_code);
+    EXPECT_EQ(req.client->response_head()->web_bundle_url, GURL(kBundleUrl));
+    std::string body;
+    EXPECT_TRUE(
+        mojo::BlockingCopyToString(req.client->response_body_release(), &body));
+    EXPECT_EQ("body", body);
+  }
 }
 
 TEST_F(WebBundleManagerTest, MemoryQuota_StartRequestAfterError) {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index bbd30f3..d9886f8 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5756,21 +5756,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -5783,7 +5783,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
@@ -5921,21 +5921,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -5947,7 +5947,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "args": [
@@ -6067,21 +6067,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -6093,7 +6093,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index c213824..83795688 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -85847,21 +85847,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -85869,7 +85869,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
@@ -85982,28 +85982,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "args": [
@@ -86103,28 +86103,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
@@ -87462,20 +87462,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -87489,7 +87489,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "merge": {
@@ -87627,20 +87627,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -87653,7 +87653,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "args": [
@@ -87773,20 +87773,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -87799,7 +87799,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "merge": {
@@ -89295,20 +89295,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -89322,7 +89322,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "merge": {
@@ -89460,20 +89460,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -89486,7 +89486,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "args": [
@@ -89606,20 +89606,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -89632,7 +89632,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "merge": {
@@ -90367,20 +90367,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -90393,7 +90393,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 74498614..37e3556 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -20875,21 +20875,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5201.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -20902,7 +20902,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
@@ -21040,21 +21040,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -21066,7 +21066,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "args": [
@@ -21186,21 +21186,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5201.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 106.0.5202.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v106.0.5201.0",
-              "revision": "version:106.0.5201.0"
+              "location": "lacros_version_skew_tests_v106.0.5202.0",
+              "revision": "version:106.0.5202.0"
             }
           ],
           "dimension_sets": [
@@ -21212,7 +21212,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 106.0.5201.0"
+        "variant_id": "Lacros version skew testing ash 106.0.5202.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 9377691..ecc4d5d 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5201.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v106.0.5202.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 106.0.5201.0',
+    'identifier': 'Lacros version skew testing ash 106.0.5202.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v106.0.5201.0',
-          'revision': 'version:106.0.5201.0',
+          'location': 'lacros_version_skew_tests_v106.0.5202.0',
+          'revision': 'version:106.0.5202.0',
         },
       ],
     },
@@ -1181,4 +1181,4 @@
       'win10_nvidia_gtx_1660_stable',
     ],
   },
-}
+}
\ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 2f649a4..1171fb56 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -595,6 +595,24 @@
             ]
         }
     ],
+    "ArcVmLimitCacheBalloonPolicy": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "ResponsiveBalloonDeflation_20220706",
+                    "params": {
+                        "responsive": "true"
+                    },
+                    "enable_features": [
+                        "ArcVmBalloonPolicy"
+                    ]
+                }
+            ]
+        }
+    ],
     "ArcVmMemorySize": [
         {
             "platforms": [
diff --git a/third_party/blink/perf_tests/paint/wavy-decorations-long.html b/third_party/blink/perf_tests/paint/wavy-decorations-long.html
new file mode 100644
index 0000000..09432c6
--- /dev/null
+++ b/third_party/blink/perf_tests/paint/wavy-decorations-long.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Wavy decoration painting: one long decoration</title>
+<script src="../resources/runner.js"></script>
+<script src="resources/paint.js"></script>
+<style>
+* {
+  text-decoration-skip: none;
+  text-decoration-skip-ink: none;
+}
+main {
+  text-decoration: red wavy underline;
+}
+main.blue {
+  text-decoration: blue wavy underline;
+}
+</style>
+<main>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </main>
+<script>
+  const main = document.querySelector("main");
+  main.innerHTML = main.innerHTML.repeat(420);
+
+  measurePaint({
+    description: "Measure frame time for painting wavy decorations with one long decoration",
+    run: () => void document.querySelector("main").classList.toggle("blue"),
+  });
+</script>
diff --git a/third_party/blink/perf_tests/paint/wavy-decorations-many.html b/third_party/blink/perf_tests/paint/wavy-decorations-many.html
new file mode 100644
index 0000000..921242c
--- /dev/null
+++ b/third_party/blink/perf_tests/paint/wavy-decorations-many.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Wavy decoration painting: many short decorations</title>
+<script src="../resources/runner.js"></script>
+<script src="resources/paint.js"></script>
+<style>
+* {
+  text-decoration-skip: none;
+  text-decoration-skip-ink: none;
+}
+main > span {
+  text-decoration: red wavy underline;
+}
+main.blue > span {
+  text-decoration: blue wavy underline;
+}
+</style>
+<main><span>Lorem</span> <span>ipsum</span> <span>dolor</span> <span>sit</span> <span>amet,</span> <span>consectetur</span> <span>adipiscing</span> <span>elit,</span> <span>sed</span> <span>do</span> <span>eiusmod</span> <span>tempor</span> <span>incididunt</span> <span>ut</span> <span>labore</span> <span>et</span> <span>dolore</span> <span>magna</span> <span>aliqua.</span> </main>
+<script>
+  const main = document.querySelector("main");
+  main.innerHTML = main.innerHTML.repeat(420);
+
+  measurePaint({
+    description: "Measure frame time for painting wavy decorations with many short decorations",
+    run: () => void document.querySelector("main").classList.toggle("blue"),
+  });
+</script>
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index e82bb019..7d98e64 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3631,6 +3631,8 @@
   kSendBeaconWithUSVString = 4310,
   kReplacedElementPaintedWithOverflow = 4311,
   kImageAd = 4312,
+  kLinkRelPrefetchAsDocumentSameOrigin = 4313,
+  kLinkRelPrefetchAsDocumentCrossOrigin = 4314,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/core/css/check_pseudo_has_argument_context.cc b/third_party/blink/renderer/core/css/check_pseudo_has_argument_context.cc
index c11c758..f7898264 100644
--- a/third_party/blink/renderer/core/css/check_pseudo_has_argument_context.cc
+++ b/third_party/blink/renderer/core/css/check_pseudo_has_argument_context.cc
@@ -34,12 +34,6 @@
   bool contains_child_or_descendant_combinator = false;
   bool sibling_combinator_at_leftmost = false;
 
-  // The explicit ':scope' in ':has' argument selector is not considered
-  // for getting the depth and adjacent distance.
-  // TODO(blee@igalia.com) Need to clarify the :scope dependency in relative
-  // selector definition.
-  // - spec : https://www.w3.org/TR/selectors-4/#relative
-  // - csswg issue : https://github.com/w3c/csswg-drafts/issues/6399
   for (selector = GetCurrentRelationAndNextCompound(selector, relation);
        selector;
        selector = GetCurrentRelationAndNextCompound(selector, relation)) {
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5
index fe9259a..77096fb 100644
--- a/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -1,7 +1,8 @@
 {
   // The mode argument is used to limit the keyword to be used only for certain
   // CSSParserModes. Values that have the prefix -internal- are only allowed by
-  // CSSParserModes listed in allowInternalPropertyAndValue()
+  // CSSParserModes listed in CSSValueKeywordsWriter, which feeds the generated
+  // code for isValueAllowedInMode.
 
   parameters: {
     mode: {},
@@ -243,6 +244,11 @@
     // Value used to implement the behavior in:
     // https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
     "-internal-quirk-inherit",
+    //
+    // css-text-decor
+    // <https://github.com/w3c/csswg-drafts/issues/7522>
+    "-internal-spelling-error-color",
+    "-internal-grammar-error-color",
 
     //
     // "Extended" named colors
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 6d7945a..fa1846a 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
@@ -354,4 +354,34 @@
       CSSParserMode::kHTMLStandardMode));
 }
 
+TEST(CSSParserFastPathsTest, InternalColorsOnlyAllowedInUaMode) {
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("blue", kHTMLStandardMode),
+            CSSIdentifierValue::Create(CSSValueID::kBlue));
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("blue", kHTMLQuirksMode),
+            CSSIdentifierValue::Create(CSSValueID::kBlue));
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("blue", kUASheetMode),
+            CSSIdentifierValue::Create(CSSValueID::kBlue));
+
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("-internal-spelling-error-color",
+                                           kHTMLStandardMode),
+            nullptr);
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("-internal-spelling-error-color",
+                                           kHTMLQuirksMode),
+            nullptr);
+  EXPECT_EQ(
+      CSSParserFastPaths::ParseColor("-internal-spelling-error-color",
+                                     kUASheetMode),
+      CSSIdentifierValue::Create(CSSValueID::kInternalSpellingErrorColor));
+
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("-internal-grammar-error-color",
+                                           kHTMLStandardMode),
+            nullptr);
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("-internal-grammar-error-color",
+                                           kHTMLQuirksMode),
+            nullptr);
+  EXPECT_EQ(CSSParserFastPaths::ParseColor("-internal-grammar-error-color",
+                                           kUASheetMode),
+            CSSIdentifierValue::Create(CSSValueID::kInternalGrammarErrorColor));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
index c237b6a2..96245fe 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
@@ -23,9 +23,9 @@
 using css_parsing_utils::ConsumeIfDelimiter;
 using css_parsing_utils::ConsumeIfIdent;
 
-CSSParserContext* MakeContext() {
+CSSParserContext* MakeContext(CSSParserMode mode = kHTMLStandardMode) {
   return MakeGarbageCollected<CSSParserContext>(
-      kHTMLStandardMode, SecureContextMode::kInsecureContext);
+      mode, SecureContextMode::kInsecureContext);
 }
 
 TEST(CSSParsingUtilsTest, BasicShapeUseCount) {
@@ -319,5 +319,39 @@
   }
 }
 
+TEST(CSSParsingUtilsTest, InternalColorsOnlyAllowedInUaMode) {
+  auto ConsumeColorForTest = [](String css_text, CSSParserMode mode) {
+    auto tokens = CSSTokenizer(css_text).TokenizeToEOF();
+    CSSParserTokenRange range(tokens);
+    return css_parsing_utils::ConsumeColor(range, *MakeContext(mode));
+  };
+
+  struct {
+    STACK_ALLOCATED();
+
+   public:
+    String css_text;
+    CSSIdentifierValue* ua_expectation;
+    CSSIdentifierValue* other_expectation;
+  } expectations[]{
+      {"blue", CSSIdentifierValue::Create(CSSValueID::kBlue),
+       CSSIdentifierValue::Create(CSSValueID::kBlue)},
+      {"-internal-spelling-error-color",
+       CSSIdentifierValue::Create(CSSValueID::kInternalSpellingErrorColor),
+       nullptr},
+      {"-internal-grammar-error-color",
+       CSSIdentifierValue::Create(CSSValueID::kInternalGrammarErrorColor),
+       nullptr},
+  };
+  for (auto& expectation : expectations) {
+    EXPECT_EQ(ConsumeColorForTest(expectation.css_text, kHTMLStandardMode),
+              expectation.other_expectation);
+    EXPECT_EQ(ConsumeColorForTest(expectation.css_text, kHTMLQuirksMode),
+              expectation.other_expectation);
+    EXPECT_EQ(ConsumeColorForTest(expectation.css_text, kUASheetMode),
+              expectation.ua_expectation);
+  }
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 4fade99..a71ae2ab 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -3242,6 +3242,7 @@
 void InternalVisitedColor::ApplyInitial(StyleResolverState& state) const {
   state.Style()->SetInternalVisitedColor(
       state.Style()->InitialColorForColorScheme());
+  state.Style()->SetInternalVisitedColorIsCurrentColor(false);
 }
 
 void InternalVisitedColor::ApplyInherit(StyleResolverState& state) const {
@@ -3252,6 +3253,8 @@
   } else {
     style->SetInternalVisitedColor(state.ParentStyle()->GetColor());
   }
+  state.Style()->SetInternalVisitedColorIsCurrentColor(
+      state.ParentStyle()->InternalVisitedColorIsCurrentColor());
 }
 
 void InternalVisitedColor::ApplyValue(StyleResolverState& state,
@@ -3260,16 +3263,23 @@
   if (identifier_value &&
       identifier_value->GetValueID() == CSSValueID::kCurrentcolor) {
     ApplyInherit(state);
+    state.Style()->SetInternalVisitedColorIsCurrentColor(true);
+    if (state.UsesHighlightPseudoInheritance() &&
+        state.OriginatingElementStyle()) {
+      state.Style()->SetInternalVisitedColor(
+          state.OriginatingElementStyle()->InternalVisitedColor());
+    }
     return;
   }
   if (value.IsInitialColorValue()) {
     DCHECK_EQ(state.GetElement(), state.GetDocument().documentElement());
     state.Style()->SetInternalVisitedColor(
         state.Style()->InitialColorForColorScheme());
-    return;
+  } else {
+    state.Style()->SetInternalVisitedColor(
+        StyleBuilderConverter::ConvertStyleColor(state, value, true));
   }
-  state.Style()->SetInternalVisitedColor(
-      StyleBuilderConverter::ConvertStyleColor(state, value, true));
+  state.Style()->SetInternalVisitedColorIsCurrentColor(false);
 }
 
 const blink::Color InternalVisitedColor::ColorIncludingFallback(
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 25b77c0..59c57c3 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -909,9 +909,13 @@
   // The computed value of currentColor for highlight pseudos is the
   // color that would have been used if no highlights were applied,
   // i.e. the originating element's color.
-  if (state.UsesHighlightPseudoInheritance() && style.ColorIsCurrentColor() &&
+  if (state.UsesHighlightPseudoInheritance() &&
       state.OriginatingElementStyle()) {
-    style.SetColor(state.OriginatingElementStyle()->GetColor());
+    const ComputedStyle* originating_style = state.OriginatingElementStyle();
+    if (style.ColorIsCurrentColor())
+      style.SetColor(originating_style->GetColor());
+    if (style.InternalVisitedColorIsCurrentColor())
+      style.SetInternalVisitedColor(originating_style->InternalVisitedColor());
   }
 
   if (style.Display() != EDisplay::kContents) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index c3824b5..36eac53 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -963,11 +963,6 @@
     // the element has rules but no matched properties, we currently clone.
 
     state.SetStyle(ComputedStyle::Clone(*state.ParentStyle()));
-    state.Style()->SetInsideLink(state.ElementLinkState());
-    state.Style()->SetInForcedColorsMode(
-        style_request.originating_element_style->InForcedColorsMode());
-    state.Style()->SetForcedColorAdjust(
-        style_request.originating_element_style->ForcedColorAdjust());
   } else {
     scoped_refptr<ComputedStyle> style = CreateComputedStyle();
     style->InheritFrom(
@@ -1013,6 +1008,17 @@
   state.Style()->SetStyleType(style_request.pseudo_id);
   state.Style()->SetPseudoArgument(style_request.pseudo_argument);
 
+  // For highlight inheritance, propagate link visitedness and forced-colors
+  // status from the originating element, even if we have no parent highlight
+  // ComputedStyle we can inherit from.
+  if (UsesHighlightPseudoInheritance(style_request.pseudo_id)) {
+    state.Style()->SetInsideLink(state.ElementLinkState());
+    state.Style()->SetInForcedColorsMode(
+        style_request.originating_element_style->InForcedColorsMode());
+    state.Style()->SetForcedColorAdjust(
+        style_request.originating_element_style->ForcedColorAdjust());
+  }
+
   if (!style_request.IsPseudoStyleRequest() && element.IsLink()) {
     state.Style()->SetIsLink();
     EInsideLink link_state = state.ElementLinkState();
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index e7881abe..9fb2bd94 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -74,20 +74,19 @@
       can_cache_base_style_(blink::CanCacheBaseStyle(style_request)) {
   DCHECK(!!parent_style_ == !!layout_parent_style_);
 
-  if (!parent_style_) {
-    parent_style_ = element_context_.ParentStyle();
+  if (UsesHighlightPseudoInheritance()) {
+    DCHECK(originating_element_style_);
+  } else {
+    if (!parent_style_)
+      parent_style_ = element_context_.ParentStyle();
+    if (!layout_parent_style_)
+      layout_parent_style_ = element_context_.LayoutParentStyle();
   }
 
   if (!layout_parent_style_)
-    layout_parent_style_ = element_context_.LayoutParentStyle();
-
-  if (!layout_parent_style_)
     layout_parent_style_ = parent_style_;
 
   DCHECK(document.IsActive());
-
-  if (UsesHighlightPseudoInheritance())
-    DCHECK(originating_element_style_);
 }
 
 StyleResolverState::~StyleResolverState() {
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc
index 87d0438..fa364f79 100644
--- a/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -727,13 +727,41 @@
   return false;
 }
 
+inline bool CacheMatchedElementsAndReturnMatchedResult(
+    CSSSelector::RelationType leftmost_relation,
+    Element* has_anchor_element,
+    HeapVector<Member<Element>>& has_argument_leftmost_compound_matches,
+    CheckPseudoHasCacheScope::Context& cache_scope_context) {
+  switch (leftmost_relation) {
+    case CSSSelector::kRelativeDescendant:
+      return CacheMatchedElementsAndReturnMatchedResultForIndirectRelation(
+          has_anchor_element, has_argument_leftmost_compound_matches,
+          cache_scope_context, TraverseToParent);
+    case CSSSelector::kRelativeChild:
+      return CacheMatchedElementsAndReturnMatchedResultForDirectRelation(
+          has_anchor_element, has_argument_leftmost_compound_matches,
+          cache_scope_context, TraverseToParent);
+    case CSSSelector::kRelativeDirectAdjacent:
+      return CacheMatchedElementsAndReturnMatchedResultForDirectRelation(
+          has_anchor_element, has_argument_leftmost_compound_matches,
+          cache_scope_context, TraverseToPreviousSibling);
+    case CSSSelector::kRelativeIndirectAdjacent:
+      return CacheMatchedElementsAndReturnMatchedResultForIndirectRelation(
+          has_anchor_element, has_argument_leftmost_compound_matches,
+          cache_scope_context, TraverseToPreviousSibling);
+    default:
+      NOTREACHED();
+      return false;
+  }
+}
+
 inline bool ContextForSubjectHasInMatchesArgument(
     const SelectorChecker::SelectorCheckingContext& has_checking_context) {
   return has_checking_context.element == has_checking_context.scope &&
          has_checking_context.in_rightmost_compound;
 }
 
-uint8_t SetHasScopeElementAsCheckedAndGetOldResult(
+uint8_t SetHasAnchorElementAsCheckedAndGetOldResult(
     const SelectorChecker::SelectorCheckingContext& has_checking_context,
     CheckPseudoHasCacheScope::Context& cache_scope_context) {
   DCHECK_EQ(has_checking_context.selector->GetPseudoType(),
@@ -774,7 +802,7 @@
   }
 }
 
-void SetAffectedByHasFlagsForHasScopeElement(
+void SetAffectedByHasFlagsForHasAnchorElement(
     CheckPseudoHasArgumentContext& argument_context,
     Element* has_anchor_element) {
   switch (argument_context.LeftmostRelation()) {
@@ -793,7 +821,7 @@
   }
 }
 
-void SetAffectedByHasFlagsForHasScopeSiblings(
+void SetAffectedByHasFlagsForHasAnchorSiblings(
     CheckPseudoHasArgumentContext& argument_context,
     Element* has_anchor_element) {
   if (argument_context.AdjacentDistanceLimit() == 0)
@@ -918,6 +946,42 @@
   return false;
 }
 
+enum EarlyBreakOnHasArgumentChecking {
+  kBreakEarlyAndReturnAsMatched,
+  kBreakEarlyAndMoveToNextArgument,
+  kNoEarlyBreak,
+};
+
+EarlyBreakOnHasArgumentChecking CheckEarlyBreakForHasArgument(
+    const SelectorChecker::SelectorCheckingContext& context,
+    Element* has_anchor_element,
+    CheckPseudoHasArgumentContext& argument_context,
+    CheckPseudoHasCacheScope::Context& cache_scope_context,
+    bool update_affected_by_has_flags) {
+  if (!cache_scope_context.CacheAllowed())
+    return kNoEarlyBreak;
+
+  // Get the cached :has() checking result of the element to skip :has()
+  // argument checking.
+  //  - If the element was already marked as matched, break :has() argument
+  //    checking early and return as matched.
+  //  - If the element was already checked but not matched, break :has()
+  //    argument checking early and move to the next argument selector.
+  //  - Otherwise, check :has() argument.
+  uint8_t previous_result =
+      SetHasAnchorElementAsCheckedAndGetOldResult(context, cache_scope_context);
+  if (previous_result & kChecked) {
+    if (update_affected_by_has_flags) {
+      SetAffectedByHasFlagsForHasAnchorSiblings(argument_context,
+                                                has_anchor_element);
+    }
+    return previous_result & kMatched ? kBreakEarlyAndReturnAsMatched
+                                      : kBreakEarlyAndMoveToNextArgument;
+  }
+
+  return kNoEarlyBreak;
+}
+
 }  // namespace
 
 bool SelectorChecker::CheckPseudoHas(const SelectorCheckingContext& context,
@@ -934,6 +998,7 @@
   // :visited matching when it is in the :has argument
   sub_context.is_inside_has_pseudo_class = true;
   sub_context.pseudo_has_in_rightmost_compound = context.in_rightmost_compound;
+  bool update_affected_by_has_flags = mode_ == kResolvingStyle;
 
   DCHECK(context.selector->SelectorList());
   for (const CSSSelector* selector = context.selector->SelectorList()->First();
@@ -944,29 +1009,18 @@
     CheckPseudoHasCacheScope::Context cache_scope_context(&document,
                                                           argument_context);
 
-    if (mode_ == kResolvingStyle) {
-      SetAffectedByHasFlagsForHasScopeElement(argument_context,
-                                              has_anchor_element);
+    if (update_affected_by_has_flags) {
+      SetAffectedByHasFlagsForHasAnchorElement(argument_context,
+                                               has_anchor_element);
     }
 
-    if (cache_scope_context.CacheAllowed()) {
-      // Get the cached :has() checking result of the element to skip :has()
-      // argument checking.
-      //  - If the element was already marked as matched, return true.
-      //  - If the element was already checked but not matched,
-      //    move to the next argument selector.
-      uint8_t previous_result = SetHasScopeElementAsCheckedAndGetOldResult(
-          context, cache_scope_context);
-      if (previous_result & kChecked) {
-        if (mode_ == kResolvingStyle) {
-          SetAffectedByHasFlagsForHasScopeSiblings(argument_context,
-                                                   has_anchor_element);
-        }
-        if (previous_result & kMatched)
-          return true;
-        continue;
-      }
-    }
+    EarlyBreakOnHasArgumentChecking early_break = CheckEarlyBreakForHasArgument(
+        context, has_anchor_element, argument_context, cache_scope_context,
+        update_affected_by_has_flags);
+    if (early_break == kBreakEarlyAndReturnAsMatched)
+      return true;
+    else if (early_break == kBreakEarlyAndMoveToNextArgument)
+      continue;
 
     sub_context.selector = selector;
     sub_context.relative_anchor_element = has_anchor_element;
@@ -977,7 +1031,7 @@
     for (CheckPseudoHasArgumentTraversalIterator iterator(*has_anchor_element,
                                                           argument_context);
          !iterator.AtEnd(); ++iterator) {
-      if (mode_ == kResolvingStyle) {
+      if (update_affected_by_has_flags) {
         SetAffectedByHasFlagsForElementAtDepth(argument_context,
                                                iterator.CurrentElement(),
                                                iterator.CurrentDepth());
@@ -997,35 +1051,9 @@
       last_argument_checked_element = iterator.CurrentElement();
       last_argument_checked_depth = iterator.CurrentDepth();
 
-      switch (leftmost_relation) {
-        case CSSSelector::kRelativeDescendant:
-          selector_matched =
-              CacheMatchedElementsAndReturnMatchedResultForIndirectRelation(
-                  has_anchor_element, has_argument_leftmost_compound_matches,
-                  cache_scope_context, TraverseToParent);
-          break;
-        case CSSSelector::kRelativeChild:
-          selector_matched =
-              CacheMatchedElementsAndReturnMatchedResultForDirectRelation(
-                  has_anchor_element, has_argument_leftmost_compound_matches,
-                  cache_scope_context, TraverseToParent);
-          break;
-        case CSSSelector::kRelativeDirectAdjacent:
-          selector_matched =
-              CacheMatchedElementsAndReturnMatchedResultForDirectRelation(
-                  has_anchor_element, has_argument_leftmost_compound_matches,
-                  cache_scope_context, TraverseToPreviousSibling);
-          break;
-        case CSSSelector::kRelativeIndirectAdjacent:
-          selector_matched =
-              CacheMatchedElementsAndReturnMatchedResultForIndirectRelation(
-                  has_anchor_element, has_argument_leftmost_compound_matches,
-                  cache_scope_context, TraverseToPreviousSibling);
-          break;
-        default:
-          NOTREACHED();
-          break;
-      }
+      selector_matched = CacheMatchedElementsAndReturnMatchedResult(
+          leftmost_relation, has_anchor_element,
+          has_argument_leftmost_compound_matches, cache_scope_context);
 
       if (selector_matched)
         break;
@@ -1036,14 +1064,15 @@
           last_argument_checked_element, last_argument_checked_depth);
     }
 
-    if (selector_matched) {
-      if (mode_ == kResolvingStyle) {
-        SetAffectedByHasForArgumentMatchedElement(
-            argument_context, has_anchor_element, last_argument_checked_element,
-            last_argument_checked_depth);
-      }
-      return true;
+    if (!selector_matched)
+      continue;
+
+    if (update_affected_by_has_flags) {
+      SetAffectedByHasForArgumentMatchedElement(
+          argument_context, has_anchor_element, last_argument_checked_element,
+          last_argument_checked_depth);
     }
+    return true;
   }
   return false;
 }
diff --git a/third_party/blink/renderer/core/css/style_color.cc b/third_party/blink/renderer/core/css/style_color.cc
index c1bc4c6..703e015 100644
--- a/third_party/blink/renderer/core/css/style_color.cc
+++ b/third_party/blink/renderer/core/css/style_color.cc
@@ -61,7 +61,13 @@
   //   '-webkit-focus-ring-color'
   //   '-internal-quirk-inherit'
   //
-  return (id >= CSSValueID::kAqua && id <= CSSValueID::kInternalQuirkInherit) ||
+  // css-text-decor
+  // <https://github.com/w3c/csswg-drafts/issues/7522>
+  //   '-internal-spelling-error-color'
+  //   '-internal-grammar-error-color'
+  //
+  return (id >= CSSValueID::kAqua &&
+          id <= CSSValueID::kInternalGrammarErrorColor) ||
          (id >= CSSValueID::kAliceblue && id <= CSSValueID::kYellowgreen) ||
          id == CSSValueID::kMenu;
 }
@@ -84,6 +90,8 @@
     case CSSValueID::kGraytext:
     case CSSValueID::kHighlight:
     case CSSValueID::kHighlighttext:
+    case CSSValueID::kInternalGrammarErrorColor:
+    case CSSValueID::kInternalSpellingErrorColor:
     case CSSValueID::kLinktext:
     case CSSValueID::kMark:
     case CSSValueID::kMarktext:
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 6e074c3..2d8ee17 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2770,6 +2770,11 @@
             document.GetDocumentAnimations().GetAnimationsCount();
       });
 
+  // If this is a throttled local root, then we shouldn't run animation steps
+  // below, because the cc animation data structures might not even exist.
+  if (frame_->IsLocalRoot() && ShouldThrottleRendering())
+    return;
+
   if (auto* animation_host = GetCompositorAnimationHost()) {
     animation_host->SetAnimationCounts(total_animations_count);
   }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view_test.cc b/third_party/blink/renderer/core/frame/local_frame_view_test.cc
index 25b7121d8..8567a1c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view_test.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view_test.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/test/scoped_feature_list.h"
+#include "content/test/test_blink_web_unit_test_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
@@ -19,6 +20,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/paint/paint_property_tree_printer.h"
 #include "third_party/blink/renderer/core/paint/paint_timing.h"
+#include "third_party/blink/renderer/core/script/classic_script.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -79,8 +81,6 @@
   Persistent<AnimationMockChromeClient> chrome_client_;
 };
 
-using LocalFrameViewSimTest = SimTest;
-
 TEST_F(LocalFrameViewTest, SetPaintInvalidationDuringUpdateAllLifecyclePhases) {
   SetBodyInnerHTML("<div id='a' style='color: blue'>A</div>");
   GetDocument().getElementById("a")->setAttribute(html_names::kStyleAttr,
@@ -320,6 +320,8 @@
       frame_view->RequiresMainThreadScrollingForBackgroundAttachmentFixed());
 }
 
+class LocalFrameViewSimTest : public SimTest {};
+
 // Ensure the fragment navigation "scroll into view and focus" behavior doesn't
 // activate synchronously while rendering is blocked waiting on a stylesheet.
 // See https://crbug.com/851338.
@@ -565,6 +567,39 @@
   EXPECT_TRUE(inner_frame_timing.FirstEligibleToPaint().is_null());
 }
 
+class LocalFrameViewRemoteParentSimTest : public LocalFrameViewSimTest {
+ public:
+  LocalFrameViewRemoteParentSimTest() {
+    content::TestBlinkWebUnitTestSupport::SetThreadedAnimationEnabled(true);
+  }
+  void SetUp() override {
+    LocalFrameViewSimTest::SetUp();
+    InitializeRemote();
+  }
+};
+
+TEST_F(LocalFrameViewRemoteParentSimTest, ThrottledLocalRootAnimationUpdate) {
+  SimRequest main_resource("https://example.com/", "text/html");
+  LoadURL("https://example.com/");
+  main_resource.Complete("<div>Hello, world!</div>");
+  Document* document = LocalFrameRoot().GetFrame()->GetDocument();
+
+  // Emulate user-land script
+  WebString source = WebString::FromASCII(R"JS(
+    let div = document.querySelector('div');
+    let kf = [ { transform: 'rotate(0)' }, { transform: 'rotate(180deg)' } ];
+    let tm = { duration: 1000, iterations: Infinity };
+    let an = div.animate(kf, tm);
+  )JS");
+  ClassicScript::CreateUnspecifiedScript(source)->RunScript(
+      document->domWindow());
+  Compositor().BeginFrame();
+  // Emulate FrameWidget.UpdateRenderThrottlingStatusForSubFrame mojo message.
+  // When the local root frame is throttled, cc animation update steps should
+  // not run.
+  document->View()->UpdateRenderThrottlingStatus(true, false, false, true);
+}
+
 class TestLifecycleObserver
     : public GarbageCollected<TestLifecycleObserver>,
       public LocalFrameView::LifecycleNotificationObserver {
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.cc
index 25d9652c..2d23ab2 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.cc
@@ -151,6 +151,9 @@
   if (IsInRegion())
     return HTMLDivElement::CreateLayoutObject(style, legacy);
 
+  // We create a standard block-flow container.
+  // See the comment in vtt_cue_layout_algorithm.h about how we adjust
+  // VTTCueBox positions.
   if (RuntimeEnabledFeatures::LayoutNGVTTCueEnabled())
     return LayoutObjectFactory::CreateBlockFlow(*this, style, legacy);
 
@@ -184,7 +187,8 @@
   return parentNode() && !IsA<TextTrackContainer>(parentNode());
 }
 
-LayoutUnit& VTTCueBox::StartAdjustment(LayoutUnit new_value) {
+LayoutUnit& VTTCueBox::StartAdjustment(LayoutUnit new_value,
+                                       base::PassKey<VttCueLayoutAlgorithm>) {
   adjusted_position_ = new_value;
   DCHECK(IsAdjusted()) << new_value;
   return adjusted_position_;
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.h b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.h
index 6b91749c..7daf944 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.h
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_box.h
@@ -52,7 +52,8 @@
   float SnapToLinesPosition() const { return snap_to_lines_position_; }
   bool IsAdjusted() const { return adjusted_position_ != LayoutUnit::Min(); }
   // IsAdjusted() becomes true after calling this.
-  LayoutUnit& StartAdjustment(LayoutUnit new_value);
+  LayoutUnit& StartAdjustment(LayoutUnit new_value,
+                              base::PassKey<VttCueLayoutAlgorithm>);
   // IsAdjusted() becomes false after calling this.
   void RevertAdjustment();
   // Returns adjusted_position_ if IsAdjusted(), or the initial position
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.cc
index 6b2b1184..a2939626 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.cc
@@ -184,7 +184,7 @@
   // by position.
   //     Vertical: Move all the boxes in boxes right ...
   LayoutUnit& adjusted_position = cue_.StartAdjustment(
-      cue_.AdjustedPosition(full_dimension, PassKey()) + position);
+      cue_.AdjustedPosition(full_dimension, PassKey()) + position, PassKey());
 
   // 11. Remember the position of all the boxes in boxes as their specified
   // position.
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.h b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.h
index 0c96d9ba..b799e89 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.h
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue_layout_algorithm.h
@@ -22,6 +22,7 @@
 // https://w3c.github.io/webvtt/#apply-webvtt-cue-settings .
 //
 // This class is used in a ResizeObserver callback for VTTCueBox.
+// See https://bit.ly/3vfUajH for more details.
 class VttCueLayoutAlgorithm {
   STACK_ALLOCATED();
   using PassKey = base::PassKey<VttCueLayoutAlgorithm>;
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 6d67e85..5d8d46a 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -8109,10 +8109,9 @@
   if (!anchor_query)
     return nullptr;
 
-  if (const auto& reference =
-          anchor_query->anchor_references.find(StyleRef().AnchorScroll());
-      reference != anchor_query->anchor_references.end()) {
-    return reference->value->fragment->GetLayoutObject();
+  if (const NGPhysicalFragment* fragment =
+          anchor_query->Fragment(StyleRef().AnchorScroll())) {
+    return fragment->GetLayoutObject();
   }
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/layout/layout_theme.cc b/third_party/blink/renderer/core/layout/layout_theme.cc
index 5212d4d..3687f5b 100644
--- a/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -635,6 +635,10 @@
       return InactiveListBoxSelectionBackgroundColor(color_scheme);
     case CSSValueID::kInternalInactiveListBoxSelectionText:
       return InactiveListBoxSelectionForegroundColor(color_scheme);
+    case CSSValueID::kInternalSpellingErrorColor:
+      return PlatformSpellingMarkerUnderlineColor();
+    case CSSValueID::kInternalGrammarErrorColor:
+      return PlatformGrammarMarkerUnderlineColor();
     default:
       break;
   }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
index f3197a6..2ec9f26b 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine_test.cc
@@ -665,6 +665,30 @@
             ToSimpleLayoutTree(root_layout_object));
 }
 
+// http://crbug.com/1342520
+TEST_F(LayoutNGTextCombineTest, ListMarkerWidthOfSymbol) {
+  InsertStyleElement(
+      "#root {"
+      " text-combine-upright: all;"
+      " writing-mode: vertical-lr;"
+      " font-size: 1e-7px;"
+      "}");
+  SetBodyInnerHTML("<li id=root>ab</li>");
+  auto& root = *GetElementById("root");
+  const auto& root_layout_object =
+      *To<LayoutNGBlockFlow>(root.GetLayoutObject());
+
+  EXPECT_EQ(R"DUMP(
+LayoutNGListItem LI id="root"
+  +--LayoutNGInsideListMarker ::marker
+  |  +--LayoutNGTextCombine (anonymous)
+  |  |  +--LayoutTextFragment (anonymous) ("\u2022 ")
+  +--LayoutNGTextCombine (anonymous)
+  |  +--LayoutText #text "ab"
+)DUMP",
+            ToSimpleLayoutTree(root_layout_object));
+}
+
 TEST_F(LayoutNGTextCombineTest, MultipleTextNode) {
   InsertStyleElement(
       "c { text-combine-upright: all; }"
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 4199a04..59ee3c33 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -2098,7 +2098,7 @@
   const float desired_width = text_combine.DesiredWidth();
   text_combine.ResetLayout();
   if (UNLIKELY(desired_width == 0.0f)) {
-    NOTREACHED() << "We get the test case!";
+    // See http://crbug.com/1342520
     return;
   }
   if (content_width <= desired_width)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_anchor_query.cc b/third_party/blink/renderer/core/layout/ng/ng_anchor_query.cc
index c808eaa..5baec74f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_anchor_query.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_anchor_query.cc
@@ -9,12 +9,69 @@
 
 namespace blink {
 
-void NGPhysicalAnchorReference::Trace(Visitor* visitor) const {
-  visitor->Trace(fragment);
+const NGPhysicalAnchorReference* NGPhysicalAnchorQuery::AnchorReference(
+    const AtomicString& name) const {
+  const auto& it = anchor_references_.find(name);
+  if (it != anchor_references_.end())
+    return it->value.Get();
+  return nullptr;
 }
 
-void NGPhysicalAnchorQuery::Trace(Visitor* visitor) const {
-  visitor->Trace(anchor_references);
+const PhysicalRect* NGPhysicalAnchorQuery::Rect(
+    const AtomicString& name) const {
+  if (const NGPhysicalAnchorReference* reference = AnchorReference(name))
+    return &reference->rect;
+  return nullptr;
+}
+
+const NGPhysicalFragment* NGPhysicalAnchorQuery::Fragment(
+    const AtomicString& name) const {
+  if (const NGPhysicalAnchorReference* reference = AnchorReference(name))
+    return reference->fragment.Get();
+  return nullptr;
+}
+
+const NGLogicalAnchorReference* NGLogicalAnchorQuery::AnchorReference(
+    const AtomicString& name) const {
+  const auto& it = anchor_references_.find(name);
+  if (it != anchor_references_.end())
+    return &it->value;
+  return nullptr;
+}
+
+const LogicalRect* NGLogicalAnchorQuery::Rect(const AtomicString& name) const {
+  if (const NGLogicalAnchorReference* reference = AnchorReference(name))
+    return &reference->rect;
+  return nullptr;
+}
+
+const NGPhysicalFragment* NGLogicalAnchorQuery::Fragment(
+    const AtomicString& name) const {
+  if (const NGLogicalAnchorReference* reference = AnchorReference(name))
+    return reference->fragment;
+  return nullptr;
+}
+
+void NGPhysicalAnchorQuery::SetFromLogical(
+    const NGLogicalAnchorQuery& logical_query,
+    const WritingModeConverter& converter) {
+  for (const auto& it : logical_query.anchor_references_) {
+    anchor_references_.Set(
+        it.key, MakeGarbageCollected<NGPhysicalAnchorReference>(
+                    converter.ToPhysical(it.value.rect), it.value.fragment));
+  }
+}
+
+void NGLogicalAnchorQuery::SetFromPhysical(
+    const NGPhysicalAnchorQuery& physical_query,
+    const WritingModeConverter& converter,
+    const LogicalOffset& additional_offset) {
+  for (const auto& it : physical_query.anchor_references_) {
+    LogicalRect rect = converter.ToLogical(it.value->rect);
+    rect.offset += additional_offset;
+    anchor_references_.Set(
+        it.key, NGLogicalAnchorReference{rect, it.value->fragment.Get()});
+  }
 }
 
 absl::optional<LayoutUnit> NGLogicalAnchorQuery::EvaluateAnchor(
@@ -24,11 +81,11 @@
     const WritingModeConverter& container_converter,
     bool is_y_axis,
     bool is_right_or_bottom) const {
-  const auto it = anchor_references.find(anchor_name);
-  if (it == anchor_references.end())
+  const NGLogicalAnchorReference* reference = AnchorReference(anchor_name);
+  if (!reference)
     return absl::nullopt;  // No targets.
 
-  const PhysicalRect anchor = container_converter.ToPhysical(it->value.rect);
+  const PhysicalRect anchor = container_converter.ToPhysical(reference->rect);
   LayoutUnit value;
   switch (anchor_value) {
     case AnchorValue::kLeft:
@@ -68,11 +125,11 @@
     AnchorSizeValue anchor_size_value,
     WritingMode container_writing_mode,
     WritingMode self_writing_mode) const {
-  const auto it = anchor_references.find(anchor_name);
-  if (it == anchor_references.end())
+  const NGLogicalAnchorReference* reference = AnchorReference(anchor_name);
+  if (!reference)
     return absl::nullopt;  // No targets.
 
-  const LogicalSize& anchor = it->value.rect.size;
+  const LogicalSize& anchor = reference->rect.size;
   switch (anchor_size_value) {
     case AnchorSizeValue::kInline:
       return anchor.inline_size;
@@ -101,4 +158,12 @@
   return absl::nullopt;
 }
 
+void NGPhysicalAnchorReference::Trace(Visitor* visitor) const {
+  visitor->Trace(fragment);
+}
+
+void NGPhysicalAnchorQuery::Trace(Visitor* visitor) const {
+  visitor->Trace(anchor_references_);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_anchor_query.h b/third_party/blink/renderer/core/layout/ng/ng_anchor_query.h
index fb87054..e668043 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_anchor_query.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_anchor_query.h
@@ -17,6 +17,7 @@
 
 namespace blink {
 
+class NGLogicalAnchorQuery;
 class NGPhysicalFragment;
 class WritingModeConverter;
 
@@ -26,31 +27,69 @@
                             const NGPhysicalFragment* fragment)
       : rect(rect), fragment(fragment) {}
 
+  void Trace(Visitor* visitor) const;
+
   PhysicalRect rect;
   Member<const NGPhysicalFragment> fragment;
-
-  void Trace(Visitor* visitor) const;
 };
 
-struct NGPhysicalAnchorQuery {
-  bool IsEmpty() const { return anchor_references.IsEmpty(); }
+class NGPhysicalAnchorQuery {
+  DISALLOW_NEW();
 
-  HeapHashMap<AtomicString, Member<NGPhysicalAnchorReference>>
-      anchor_references;
+ public:
+  bool IsEmpty() const { return anchor_references_.IsEmpty(); }
+
+  const NGPhysicalAnchorReference* AnchorReference(
+      const AtomicString& name) const;
+  const PhysicalRect* Rect(const AtomicString& name) const;
+  const NGPhysicalFragment* Fragment(const AtomicString& name) const;
+
+  using NGPhysicalAnchorReferenceMap =
+      HeapHashMap<AtomicString, Member<NGPhysicalAnchorReference>>;
+  NGPhysicalAnchorReferenceMap::const_iterator begin() const {
+    return anchor_references_.begin();
+  }
+  NGPhysicalAnchorReferenceMap::const_iterator end() const {
+    return anchor_references_.end();
+  }
+
+  void SetFromLogical(const NGLogicalAnchorQuery& logical_query,
+                      const WritingModeConverter& converter);
 
   void Trace(Visitor* visitor) const;
-  DISALLOW_NEW();
+
+ private:
+  friend class NGLogicalAnchorQuery;
+
+  NGPhysicalAnchorReferenceMap anchor_references_;
 };
 
 struct NGLogicalAnchorReference {
+  STACK_ALLOCATED();
+
+ public:
   LogicalRect rect;
   const NGPhysicalFragment* fragment;
-
-  STACK_ALLOCATED();
 };
 
-struct NGLogicalAnchorQuery {
-  bool IsEmpty() const { return anchor_references.IsEmpty(); }
+class NGLogicalAnchorQuery {
+  STACK_ALLOCATED();
+
+ public:
+  bool IsEmpty() const { return anchor_references_.IsEmpty(); }
+
+  const NGLogicalAnchorReference* AnchorReference(
+      const AtomicString& name) const;
+  const LogicalRect* Rect(const AtomicString& name) const;
+  const NGPhysicalFragment* Fragment(const AtomicString& name) const;
+
+  void Set(const AtomicString& name,
+           const NGLogicalAnchorReference& reference) {
+    anchor_references_.Set(name, reference);
+  }
+  void SetFromPhysical(const NGPhysicalAnchorQuery& physical_query,
+                       const WritingModeConverter& converter,
+                       const LogicalOffset& additional_offset);
 
   // Evaluate the |anchor_name| for the |anchor_value|. Returns |nullopt| if
   // the query is invalid (e.g., no targets or wrong axis.)
@@ -61,15 +100,15 @@
       const WritingModeConverter& container_converter,
       bool is_y_axis,
       bool is_right_or_bottom) const;
-
   absl::optional<LayoutUnit> EvaluateSize(const AtomicString& anchor_name,
                                           AnchorSizeValue anchor_size_value,
                                           WritingMode container_writing_mode,
                                           WritingMode self_writing_mode) const;
 
-  HashMap<AtomicString, NGLogicalAnchorReference> anchor_references;
+ private:
+  friend class NGPhysicalAnchorQuery;
 
-  STACK_ALLOCATED();
+  HashMap<AtomicString, NGLogicalAnchorReference> anchor_references_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
index 1b46e38..8f7da23 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_anchor_query_test.cc
@@ -41,7 +41,7 @@
   static Vector<AnchorTestData> ToList(
       const NGPhysicalAnchorQuery& anchor_query) {
     Vector<AnchorTestData> items;
-    for (const auto& it : anchor_query.anchor_references)
+    for (const auto& it : anchor_query)
       items.push_back(AnchorTestData{it.key, it.value->rect});
     std::sort(items.begin(), items.end(),
               [](const AnchorTestData& a, const AnchorTestData& b) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index fada7068..34783a2 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -59,7 +59,7 @@
     if (const AtomicString& anchor_name = child.Style().AnchorName();
         !anchor_name.IsNull()) {
       DCHECK(RuntimeEnabledFeatures::CSSAnchorPositioningEnabled());
-      anchor_query_.anchor_references.Set(
+      anchor_query_.Set(
           anchor_name,
           NGLogicalAnchorReference{
               LogicalRect{child_offset + relative_offset,
@@ -442,14 +442,8 @@
   }
 
   // Collect any anchor references.
-  if (const NGPhysicalAnchorQuery* anchor_query = fragment.AnchorQuery()) {
-    for (const auto& it : anchor_query->anchor_references) {
-      LogicalRect rect = converter.ToLogical(it.value->rect);
-      rect.offset += adjusted_offset;
-      anchor_query_.anchor_references.Set(
-          it.key, NGLogicalAnchorReference{rect, it.value->fragment.Get()});
-    }
-  }
+  if (const NGPhysicalAnchorQuery* anchor_query = fragment.AnchorQuery())
+    anchor_query_.SetFromPhysical(*anchor_query, converter, adjusted_offset);
 
   NGFragmentedOutOfFlowData* oof_data = fragment.FragmentedOutOfFlowData();
   if (!oof_data)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
index 790f43c..84cfb7f8 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -410,11 +410,7 @@
     if (!oof_data)
       oof_data = MakeGarbageCollected<OutOfFlowData>();
 
-    for (const auto& it : builder->anchor_query_.anchor_references) {
-      oof_data->anchor_query.anchor_references.Set(
-          it.key, MakeGarbageCollected<NGPhysicalAnchorReference>(
-                      converter.ToPhysical(it.value.rect), it.value.fragment));
-    }
+    oof_data->anchor_query.SetFromLogical(builder->anchor_query_, converter);
   }
 
   return oof_data;
diff --git a/third_party/blink/renderer/core/loader/link_loader.cc b/third_party/blink/renderer/core/loader/link_loader.cc
index 14ee9f7..5b694bf 100644
--- a/third_party/blink/renderer/core/loader/link_loader.cc
+++ b/third_party/blink/renderer/core/loader/link_loader.cc
@@ -116,8 +116,9 @@
     return false;
   }
 
-  if (params.reason != LinkLoadParameters::Reason::kMediaChange ||
-      (pending_preload_ && !pending_preload_->MatchesMedia())) {
+  if (!pending_preload_ ||
+      (params.reason != LinkLoadParameters::Reason::kMediaChange ||
+       !pending_preload_->MatchesMedia())) {
     Abort();
     pending_preload_ = MakeGarbageCollected<PendingLinkPreload>(document, this);
   }
diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc
index 45d6907..6250fb038 100644
--- a/third_party/blink/renderer/core/loader/preload_helper.cc
+++ b/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -585,6 +585,14 @@
   if (EqualIgnoringASCIICase(params.as, "document") &&
       !document.GetExecutionContext()->GetSecurityOrigin()->IsOpaque()) {
     resource_request.SetPrefetchMaybeForTopLevelNavigation(true);
+
+    bool is_same_origin =
+        document.GetExecutionContext()->GetSecurityOrigin()->IsSameOriginWith(
+            SecurityOrigin::Create(params.href).get());
+    UseCounter::Count(document,
+                      is_same_origin
+                          ? WebFeature::kLinkRelPrefetchAsDocumentSameOrigin
+                          : WebFeature::kLinkRelPrefetchAsDocumentCrossOrigin);
   }
 
   // This request could have originally been a preload header on a prefetch
diff --git a/third_party/blink/renderer/core/paint/applied_decoration_painter.cc b/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
index eeced84..bc8ae84 100644
--- a/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
+++ b/third_party/blink/renderer/core/paint/applied_decoration_painter.cc
@@ -11,15 +11,19 @@
 namespace blink {
 
 void AppliedDecorationPainter::Paint(const cc::PaintFlags* flags) {
+  ETextDecorationStyle decoration_style = decoration_info_.DecorationStyle();
+
   context_.SetStrokeStyle(decoration_info_.StrokeStyle());
   context_.SetStrokeColor(decoration_info_.LineColor());
 
   AutoDarkMode auto_dark_mode(
       PaintAutoDarkMode(decoration_info_.TargetStyle(),
                         DarkModeFilter::ElementRole::kForeground));
-  switch (decoration_info_.DecorationStyle()) {
+
+  // TODO(crbug.com/1346281) make other decoration styles work with PaintFlags
+  switch (decoration_style) {
     case ETextDecorationStyle::kWavy:
-      StrokeWavyTextDecoration(flags);
+      PaintWavyTextDecoration();
       break;
     case ETextDecorationStyle::kDotted:
     case ETextDecorationStyle::kDashed:
@@ -38,8 +42,7 @@
   }
 }
 
-void AppliedDecorationPainter::StrokeWavyTextDecoration(
-    const cc::PaintFlags* flags) {
+void AppliedDecorationPainter::PaintWavyTextDecoration() {
   // We need this because of the clipping we're doing below, as we paint both
   // overlines and underlines here. That clip would hide the overlines, when
   // painting the underlines.
@@ -49,16 +52,21 @@
 
   // The wavy line is larger than the line, as we add whole waves before and
   // after the line in TextDecorationInfo::PrepareWavyStrokePath().
-  context_.Clip(decoration_info_.Bounds());
+  gfx::PointF origin = decoration_info_.Bounds().origin();
 
-  absl::optional<Path> path = decoration_info_.StrokePath();
   AutoDarkMode auto_dark_mode(
       PaintAutoDarkMode(decoration_info_.TargetStyle(),
                         DarkModeFilter::ElementRole::kForeground));
-  if (flags)
-    context_.DrawPath(path->GetSkPath(), *flags, auto_dark_mode);
-  else
-    context_.StrokePath(path.value(), auto_dark_mode);
+  cc::PaintFlags flags;
+
+  flags.setAntiAlias(true);
+  flags.setShader(PaintShader::MakePaintRecord(
+      decoration_info_.WavyTileRecord(),
+      gfx::RectFToSkRect(decoration_info_.WavyTileRect()), SkTileMode::kRepeat,
+      SkTileMode::kDecal, nullptr));
+  context_.Translate(origin.x(), origin.y());
+  context_.DrawRect(gfx::RectFToSkRect(decoration_info_.WavyPaintRect()), flags,
+                    auto_dark_mode);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/applied_decoration_painter.h b/third_party/blink/renderer/core/paint/applied_decoration_painter.h
index e7256e27..c4b08fc 100644
--- a/third_party/blink/renderer/core/paint/applied_decoration_painter.h
+++ b/third_party/blink/renderer/core/paint/applied_decoration_painter.h
@@ -26,7 +26,7 @@
   void Paint(const cc::PaintFlags* flags = nullptr);
 
  private:
-  void StrokeWavyTextDecoration(const cc::PaintFlags* flags);
+  void PaintWavyTextDecoration();
 
   GraphicsContext& context_;
   const TextDecorationInfo& decoration_info_;
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index a61938c..f30b5b4 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -1379,10 +1379,9 @@
   EXPECT_EQ(opaque_color->SafeOpaqueBackgroundColor(), SkColors::kBlue);
 
   auto* opaque_image = CcLayerByDOMElementId("opaque-image");
-  EXPECT_TRUE(opaque_image->contents_opaque());
+  EXPECT_FALSE(opaque_image->contents_opaque());
   EXPECT_EQ(opaque_image->background_color(), SkColors::kTransparent);
-  // Fallback to use the viewport background.
-  EXPECT_EQ(opaque_image->SafeOpaqueBackgroundColor(), SkColors::kYellow);
+  EXPECT_EQ(opaque_image->SafeOpaqueBackgroundColor(), SkColors::kTransparent);
 
   const SkColor4f kTranslucentCyan{0.0f, 1.0f, 1.0f, 128.0f / 255.0f};
   auto* opaque_image_translucent_color =
diff --git a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
index e2968cc..f4414a38 100644
--- a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
+++ b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
@@ -213,7 +213,7 @@
                        !UseUaHighlightColors(pseudo, *pseudo_style))) {
     if (!document.InForcedColorsMode() ||
         pseudo_style->ForcedColorAdjust() != EForcedColorAdjust::kAuto) {
-      if (pseudo_style->ColorIsCurrentColor()) {
+      if (pseudo_style->VisitedDependentColorIsCurrentColor()) {
         if (RuntimeEnabledFeatures::HighlightOverlayPaintingEnabled())
           return previous_layer_color;
         else
@@ -288,7 +288,7 @@
       Color highlight_color =
           pseudo_style->VisitedDependentColor(GetCSSPropertyBackgroundColor());
       if (pseudo_style->IsBackgroundColorCurrentColor() &&
-          pseudo_style->ColorIsCurrentColor()) {
+          pseudo_style->VisitedDependentColorIsCurrentColor()) {
         if (RuntimeEnabledFeatures::HighlightOverlayPaintingEnabled() &&
             previous_layer_color.has_value()) {
           highlight_color = previous_layer_color.value();
diff --git a/third_party/blink/renderer/core/paint/text_decoration_info.cc b/third_party/blink/renderer/core/paint/text_decoration_info.cc
index 6eca63e..892ff4f1 100644
--- a/third_party/blink/renderer/core/paint/text_decoration_info.cc
+++ b/third_party/blink/renderer/core/paint/text_decoration_info.cc
@@ -144,6 +144,139 @@
   return stroke_style;
 }
 
+struct WavyParams {
+  float resolved_thickness;
+  bool spelling_grammar;
+  Color color;
+};
+
+float WavyDecorationSizing(const WavyParams& params) {
+  // Minimum unit we use to compute control point distance and step to define
+  // the path of the Bezier curve.
+  return std::max<float>(2, params.resolved_thickness);
+}
+
+float WavyControlPointDistance(const WavyParams& params) {
+  // Distance between decoration's axis and Bezier curve's control points. The
+  // height of the curve is based on this distance. Increases the curve's height
+  // as strokeThickness increases to make the curve look better.
+  if (params.spelling_grammar)
+    return 5;
+
+  return 3.5 * WavyDecorationSizing(params);
+}
+
+float WavyStep(const WavyParams& params) {
+  // Increment used to form the diamond shape between start point (p1), control
+  // points and end point (p2) along the axis of the decoration. Makes the curve
+  // wider as strokeThickness increases to make the curve look better.
+  if (params.spelling_grammar)
+    return 3;
+
+  return 2.5 * WavyDecorationSizing(params);
+}
+
+// Computes the wavy pattern rect, which is where the desired wavy pattern would
+// be found when painting the wavy stroke path at the origin, or in other words,
+// how far PrepareWavyTileRecord needs to translate in the opposite direction
+// when painting to ensure that nothing is painted at y<0.
+gfx::RectF ComputeWavyPatternRect(const WavyParams& params,
+                                  const Path& stroke_path) {
+  StrokeData stroke_data;
+  stroke_data.SetThickness(params.resolved_thickness);
+
+  // Expand the stroke rect to integer y coordinates in both directions, to
+  // avoid messing with the vertical antialiasing.
+  gfx::RectF stroke_rect = stroke_path.StrokeBoundingRect(stroke_data);
+  DCHECK_LT(stroke_rect.y(), 0.f);
+  float top = -std::ceilf(std::fabsf(stroke_rect.y()));
+  float bottom = std::ceilf(stroke_rect.bottom());
+  return {0.f, top, 2.f * WavyStep(params), bottom - top};
+}
+
+// Prepares a path for a cubic Bezier curve repeated three times, yielding a
+// wavy pattern that we can cut into a tiling shader (PrepareWavyTileRecord).
+//
+// The result ignores the local origin, line offset, and (wavy) double offset,
+// so the midpoints are always at y=0.5, while the phase is shifted for either
+// wavy or spelling/grammar decorations so the desired pattern starts at x=0.
+//
+// The start point, control points (cp1 and cp2), and end point of each curve
+// form a diamond shape:
+//
+//            cp2                      cp2                      cp2
+// ---         +                        +                        +
+// |               x=0
+// | control         |--- spelling/grammar ---|
+// | point          . .                      . .                      . .
+// | distance     .     .                  .     .                  .     .
+// |            .         .              .         .              .         .
+// +-- y=0.5   .            +           .            +           .            +
+//  .         .              .         .              .         .
+//    .     .                  .     .                  .     .
+//      . .                      . .                      . .
+//                          |-------- other ---------|
+//                        x=0
+//             +                        +                        +
+//            cp1                      cp1                      cp1
+// |-----------|------------|
+//     step         step
+Path PrepareWavyStrokePath(const WavyParams& params) {
+  float control_point_distance = WavyControlPointDistance(params);
+  float step = WavyStep(params);
+
+  // We paint the wave before and after the text line (to cover the whole length
+  // of the line) and then we clip it at
+  // AppliedDecorationPainter::StrokeWavyTextDecoration().
+  // Offset the start point, so the beizer curve starts before the current line,
+  // that way we can clip it exactly the same way in both ends.
+  // For spelling and grammar errors we offset by half a step less, to get a
+  // result closer to Microsoft Word circa 2021.
+  float phase_shift = (params.spelling_grammar ? -1.5f : -2.f) * step;
+
+  // Midpoints at y=0.5, to reduce vertical antialiasing.
+  gfx::PointF start{phase_shift, 0.5f};
+  gfx::PointF end{start + gfx::Vector2dF(2.f * step, 0.f)};
+  gfx::PointF cp1{start + gfx::Vector2dF(step, +control_point_distance)};
+  gfx::PointF cp2{start + gfx::Vector2dF(step, -control_point_distance)};
+
+  Path result{};
+  result.MoveTo(start);
+
+  result.AddBezierCurveTo(cp1, cp2, end);
+  cp1.set_x(cp1.x() + 2.f * step);
+  cp2.set_x(cp2.x() + 2.f * step);
+  end.set_x(end.x() + 2.f * step);
+  result.AddBezierCurveTo(cp1, cp2, end);
+  cp1.set_x(cp1.x() + 2.f * step);
+  cp2.set_x(cp2.x() + 2.f * step);
+  end.set_x(end.x() + 2.f * step);
+  result.AddBezierCurveTo(cp1, cp2, end);
+
+  return result;
+}
+
+sk_sp<cc::PaintRecord> PrepareWavyTileRecord(const WavyParams& params,
+                                             const Path& stroke_path,
+                                             const gfx::RectF& pattern_rect) {
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setColor(params.color.Rgb());
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  flags.setStrokeWidth(params.resolved_thickness);
+
+  // Create a canvas with origin (0,0) and size of the wavy pattern rect.
+  PaintRecorder recorder;
+  recorder.beginRecording(pattern_rect.width(), pattern_rect.height());
+
+  // Translate the wavy pattern so that nothing is painted at y<0.
+  cc::RecordPaintCanvas* canvas = recorder.getRecordingCanvas();
+  canvas->translate(-pattern_rect.x(), -pattern_rect.y());
+  canvas->cc::PaintCanvas::drawPath(stroke_path.GetSkPath(), flags);
+
+  return recorder.finishRecordingAsPicture();
+}
+
 }  // anonymous namespace
 
 TextDecorationInfo::TextDecorationInfo(
@@ -302,12 +435,16 @@
     case ETextDecorationStyle::kDotted:
     case ETextDecorationStyle::kDashed:
       line_data_.stroke_path = PrepareDottedOrDashedStrokePath();
+      line_data_.wavy_tile_record.reset();
       break;
     case ETextDecorationStyle::kWavy:
-      line_data_.stroke_path = PrepareWavyStrokePath();
+      line_data_.stroke_path.reset();
+      ComputeWavyLineData(line_data_.wavy_pattern_rect,
+                          line_data_.wavy_tile_record);
       break;
     default:
       line_data_.stroke_path.reset();
+      line_data_.wavy_tile_record.reset();
   }
 }
 
@@ -481,6 +618,33 @@
   return thickness;
 }
 
+void TextDecorationInfo::ComputeWavyLineData(
+    gfx::RectF& pattern_rect,
+    sk_sp<cc::PaintRecord>& tile_record) const {
+  struct WavyCache {
+    WavyParams key;
+    gfx::RectF pattern_rect;
+    sk_sp<cc::PaintRecord> tile_record;
+  };
+
+  DEFINE_STATIC_LOCAL(absl::optional<WavyCache>, wavy_cache, (absl::nullopt));
+
+  if (wavy_cache && wavy_cache->key.resolved_thickness == ResolvedThickness() &&
+      wavy_cache->key.spelling_grammar == IsSpellingOrGrammarError() &&
+      wavy_cache->key.color == LineColor()) {
+    pattern_rect = wavy_cache->pattern_rect;
+    tile_record = wavy_cache->tile_record;
+    return;
+  }
+
+  WavyParams params{ResolvedThickness(), IsSpellingOrGrammarError(),
+                    LineColor()};
+  Path stroke_path = PrepareWavyStrokePath(params);
+  pattern_rect = ComputeWavyPatternRect(params, stroke_path);
+  tile_record = PrepareWavyTileRecord(params, stroke_path, pattern_rect);
+  wavy_cache = WavyCache{params, pattern_rect, tile_record};
+}
+
 gfx::RectF TextDecorationInfo::Bounds() const {
   gfx::PointF start_point = StartPoint();
   switch (DecorationStyle()) {
@@ -513,18 +677,42 @@
   return line_data_.stroke_path.value().StrokeBoundingRect(stroke_data);
 }
 
+// Returns the wavy bounds, which is the same size as the wavy paint rect but
+// at the origin needed by the actual decoration, for the global transform.
+//
+// The origin is the sum of the local origin, line offset, (wavy) double offset,
+// and the origin of the wavy pattern rect (around minus half the amplitude).
 gfx::RectF TextDecorationInfo::BoundsForWavy() const {
-  StrokeData stroke_data;
-  stroke_data.SetThickness(ResolvedThickness());
-  auto bounding_rect = line_data_.stroke_path->StrokeBoundingRect(stroke_data);
-
-  bounding_rect.set_x(StartPoint().x());
-  bounding_rect.set_width(width_);
-  return bounding_rect;
+  gfx::SizeF size = WavyPaintRect().size();
+  gfx::PointF origin = line_data_.wavy_pattern_rect.origin();
+  origin += StartPoint().OffsetFromOrigin();
+  origin += gfx::Vector2dF{0.f, DoubleOffset() * line_data_.wavy_offset_factor};
+  return {origin, size};
 }
 
-absl::optional<Path> TextDecorationInfo::StrokePath() const {
-  return line_data_.stroke_path;
+// Returns the wavy paint rect, which has the height of the wavy tile rect but
+// the width needed by the actual decoration, for the DrawRect operation.
+//
+// The origin is still (0,0) so that the shader local matrix is independent of
+// the origin of the decoration, allowing Skia to cache the tile. To determine
+// the origin of the decoration, use Bounds().origin().
+gfx::RectF TextDecorationInfo::WavyPaintRect() const {
+  gfx::RectF result = WavyTileRect();
+  result.set_width(width_);
+  return result;
+}
+
+// Returns the wavy tile rect, which is the same size as the wavy pattern rect
+// but at origin (0,0), for converting the PaintRecord to a PaintShader.
+gfx::RectF TextDecorationInfo::WavyTileRect() const {
+  gfx::RectF result = line_data_.wavy_pattern_rect;
+  result.set_x(0.f);
+  result.set_y(0.f);
+  return result;
+}
+
+sk_sp<cc::PaintRecord> TextDecorationInfo::WavyTileRecord() const {
+  return line_data_.wavy_tile_record;
 }
 
 void TextDecorationInfo::SetHighlightOverrideColor(
@@ -532,32 +720,6 @@
   highlight_override_ = color;
 }
 
-float TextDecorationInfo::WavyDecorationSizing() const {
-  // Minimum unit we use to compute control point distance and step to define
-  // the path of the Bezier curve.
-  return std::max<float>(2, ResolvedThickness());
-}
-
-float TextDecorationInfo::ControlPointDistanceFromResolvedThickness() const {
-  // Distance between decoration's axis and Bezier curve's control points. The
-  // height of the curve is based on this distance. Increases the curve's height
-  // as strokeThickness increases to make the curve look better.
-  if (IsSpellingOrGrammarError())
-    return 5;
-
-  return 3.5 * WavyDecorationSizing();
-}
-
-float TextDecorationInfo::StepFromResolvedThickness() const {
-  // Increment used to form the diamond shape between start point (p1), control
-  // points and end point (p2) along the axis of the decoration. Makes the curve
-  // wider as strokeThickness increases to make the curve look better.
-  if (IsSpellingOrGrammarError())
-    return 3;
-
-  return 2.5 * WavyDecorationSizing();
-}
-
 Path TextDecorationInfo::PrepareDottedOrDashedStrokePath() const {
   // These coordinate transforms need to match what's happening in
   // GraphicsContext's drawLineForText and drawLine.
@@ -567,118 +729,4 @@
       TextDecorationStyleToStrokeStyle(DecorationStyle()));
 }
 
-/*
- * Prepare a path for a cubic Bezier curve and repeat the same pattern long the
- * the decoration's axis.  The start point (p1), controlPoint1, controlPoint2
- * and end point (p2) of the Bezier curve form a diamond shape:
- *
- *                              step
- *                         |-----------|
- *
- *                   controlPoint1
- *                         +
- *
- *
- *                  . .
- *                .     .
- *              .         .
- * (x1, y1) p1 +           .            + p2 (x2, y2) - <--- Decoration's axis
- *                          .         .               |
- *                            .     .                 |
- *                              . .                   | controlPointDistance
- *                                                    |
- *                                                    |
- *                         +                          -
- *                   controlPoint2
- *
- *             |-----------|
- *                 step
- */
-Path TextDecorationInfo::PrepareWavyStrokePath() const {
-  float wave_offset = DoubleOffset() * line_data_.wavy_offset_factor;
-
-  float control_point_distance = ControlPointDistanceFromResolvedThickness();
-  // For spelling and grammar errors we invert the control_point_distance to get
-  // a result closer to Microsoft Word circa 2021.
-  if (IsSpellingOrGrammarError())
-    control_point_distance = -control_point_distance;
-  float step = StepFromResolvedThickness();
-
-  gfx::PointF start_point = StartPoint();
-  // We paint the wave before and after the text line (to cover the whole length
-  // of the line) and then we clip it at
-  // AppliedDecorationPainter::StrokeWavyTextDecoration().
-  // Offset the start point, so the beizer curve starts before the current line,
-  // that way we can clip it exactly the same way in both ends.
-  // For spelling and grammar errors we offset an extra half step, to get a
-  // result closer to Microsoft Word circa 2021.
-  float start_offset = (IsSpellingOrGrammarError() ? -2.5 : -2) * step;
-  gfx::PointF p1(start_point + gfx::Vector2dF(start_offset, wave_offset));
-  // Increase the width including the previous offset, plus an extra wave to be
-  // painted after the line.
-  float extra_width = (IsSpellingOrGrammarError() ? 4.5 : 4) * step;
-  gfx::PointF p2(start_point +
-                 gfx::Vector2dF(width_ + extra_width, wave_offset));
-
-  GraphicsContext::AdjustLineToPixelBoundaries(p1, p2, ResolvedThickness());
-
-  Path path;
-  path.MoveTo(p1);
-
-  bool is_vertical_line = (p1.x() == p2.x());
-
-  if (is_vertical_line) {
-    DCHECK(p1.x() == p2.x());
-
-    float x_axis = p1.x();
-    float y1;
-    float y2;
-
-    if (p1.y() < p2.y()) {
-      y1 = p1.y();
-      y2 = p2.y();
-    } else {
-      y1 = p2.y();
-      y2 = p1.y();
-    }
-
-    gfx::PointF control_point1(x_axis + control_point_distance, 0);
-    gfx::PointF control_point2(x_axis - control_point_distance, 0);
-
-    for (float y = y1; y + 2 * step <= y2;) {
-      control_point1.set_y(y + step);
-      control_point2.set_y(y + step);
-      y += 2 * step;
-      path.AddBezierCurveTo(control_point1, control_point2,
-                            gfx::PointF(x_axis, y));
-    }
-  } else {
-    DCHECK(p1.y() == p2.y());
-
-    float y_axis = p1.y();
-    float x1;
-    float x2;
-
-    if (p1.x() < p2.x()) {
-      x1 = p1.x();
-      x2 = p2.x();
-    } else {
-      x1 = p2.x();
-      x2 = p1.x();
-    }
-
-    gfx::PointF control_point1(0, y_axis + control_point_distance);
-    gfx::PointF control_point2(0, y_axis - control_point_distance);
-
-    for (float x = x1; x + 2 * step <= x2;) {
-      control_point1.set_x(x + step);
-      control_point2.set_x(x + step);
-      x += 2 * step;
-      path.AddBezierCurveTo(control_point1, control_point2,
-                            gfx::PointF(x, y_axis));
-    }
-  }
-  return path;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/text_decoration_info.h b/third_party/blink/renderer/core/paint/text_decoration_info.h
index 8f6cff8..58a3b43c 100644
--- a/third_party/blink/renderer/core/paint/text_decoration_info.h
+++ b/third_party/blink/renderer/core/paint/text_decoration_info.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_DECORATION_INFO_H_
 
 #include "base/types/strong_alias.h"
+#include "cc/paint/paint_op_buffer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -142,8 +143,10 @@
   // Compute bounds for the given line and the current decoration.
   gfx::RectF Bounds() const;
 
-  // Return a path for current decoration.
-  absl::optional<Path> StrokePath() const;
+  // Returns tile record and coordinates for wavy decorations.
+  sk_sp<cc::PaintRecord> WavyTileRecord() const;
+  gfx::RectF WavyPaintRect() const;
+  gfx::RectF WavyTileRect() const;
 
   // Overrides the line color with the given topmost active highlight ‘color’.
   void SetHighlightOverrideColor(const absl::optional<Color>&);
@@ -154,14 +157,12 @@
   float ComputeUnderlineThickness(
       const TextDecorationThickness& applied_decoration_thickness,
       const ComputedStyle* decorating_box_style) const;
+  void ComputeWavyLineData(gfx::RectF& pattern_rect,
+                           sk_sp<cc::PaintRecord>& tile_record) const;
 
   gfx::RectF BoundsForDottedOrDashed() const;
   gfx::RectF BoundsForWavy() const;
-  float WavyDecorationSizing() const;
-  float ControlPointDistanceFromResolvedThickness() const;
-  float StepFromResolvedThickness() const;
   Path PrepareDottedOrDashedStrokePath() const;
-  Path PrepareWavyStrokePath() const;
   bool IsSpellingOrGrammarError() const {
     return line_data_.line == TextDecorationLine::kSpellingError ||
            line_data_.line == TextDecorationLine::kGrammarError;
@@ -228,8 +229,14 @@
     TextDecorationLine line;
     float line_offset;
     float double_offset;
-    int wavy_offset_factor;
+
+    // Only used for kDotted and kDashed lines.
     absl::optional<Path> stroke_path;
+
+    // Only used for kWavy lines.
+    int wavy_offset_factor;
+    gfx::RectF wavy_pattern_rect;
+    sk_sp<cc::PaintRecord> wavy_tile_record;
   };
   LineData line_data_;
   absl::optional<Color> highlight_override_;
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 13b911cc..e12d9ba1 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2420,6 +2420,12 @@
                unvisited_color.Alpha());
 }
 
+bool ComputedStyle::VisitedDependentColorIsCurrentColor() const {
+  if (InsideLink() == EInsideLink::kInsideVisitedLink)
+    return InternalVisitedColorIsCurrentColor();
+  return ColorIsCurrentColor();
+}
+
 Color ComputedStyle::ResolvedColor(const StyleColor& color) const {
   bool visited_link = (InsideLink() == EInsideLink::kInsideVisitedLink);
   Color current_color =
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 5bbddd7..eed973f2 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2748,6 +2748,7 @@
   // Color utility functions.
   CORE_EXPORT Color
   VisitedDependentColor(const CSSProperty& color_property) const;
+  CORE_EXPORT bool VisitedDependentColorIsCurrentColor() const;
 
   // -webkit-appearance utility functions.
   bool HasEffectiveAppearance() const {
@@ -2983,6 +2984,7 @@
   }
   const StyleAutoColor& CaretColor() const { return CaretColorInternal(); }
   const StyleColor& GetColor() const { return ColorInternal(); }
+  bool ColorIsCurrentColor() const { return ColorIsCurrentColorInternal(); }
   const StyleColor& ColumnRuleColor() const {
     return ColumnRuleColorInternal();
   }
@@ -3001,6 +3003,9 @@
   const StyleColor& InternalVisitedColor() const {
     return InternalVisitedColorInternal();
   }
+  bool InternalVisitedColorIsCurrentColor() const {
+    return InternalVisitedColorIsCurrentColorInternal();
+  }
   const StyleAutoColor& InternalVisitedCaretColor() const {
     return InternalVisitedCaretColorInternal();
   }
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index 418990e..c67f71c 100644
--- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -844,6 +844,16 @@
       type_name: "bool",
       default_value: "true",
       inherited: true,
+      computed_style_custom_functions: ["getter"],
+    },
+    {
+      name: "InternalVisitedColorIsCurrentColor",
+      field_template: "primitive",
+      field_group: "inherited",
+      type_name: "bool",
+      default_value: "true",
+      inherited: true,
+      computed_style_custom_functions: ["getter"],
     },
     {
       name: "WillChangeProperties",
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index e720221..2859b944 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -126,9 +126,16 @@
   cc_picture_layer_->SetHitTestable(true);
   cc_picture_layer_->SetIsDrawable(pending_layer.DrawsContent());
 
-  bool contents_opaque = pending_layer.RectKnownToBeOpaque().Contains(
-      gfx::RectF(gfx::PointAtOffsetFromOrigin(pending_layer.LayerOffset()),
-                 gfx::SizeF(pending_layer.LayerBounds())));
+  cc_picture_layer_->SetBackgroundColor(pending_layer.ComputeBackgroundColor());
+  bool contents_opaque =
+      // If the background color is transparent, don't treat the layer as opaque
+      // because we won't have a good SafeOpaqueBackgroundColor() to fill the
+      // subpixels along the edges in case the layer is not aligned to whole
+      // pixels during rasterization.
+      cc_picture_layer_->background_color() != SkColors::kTransparent &&
+      pending_layer.RectKnownToBeOpaque().Contains(
+          gfx::RectF(gfx::PointAtOffsetFromOrigin(pending_layer.LayerOffset()),
+                     gfx::SizeF(pending_layer.LayerBounds())));
   cc_picture_layer_->SetContentsOpaque(contents_opaque);
   if (!contents_opaque) {
     cc_picture_layer_->SetContentsOpaqueForText(
diff --git a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
index 82272b2..26988c7 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
@@ -34,7 +34,8 @@
     json->SetInteger("ccLayerId", layer.id());
   }
 
-  json->SetString("name", String(layer.DebugName().c_str()));
+  String debug_name(layer.DebugName());
+  json->SetString("name", debug_name);
 
   if (layer.offset_to_transform_parent() != gfx::Vector2dF()) {
     json->SetArray("position",
@@ -57,7 +58,12 @@
     json->SetString("backfaceVisibility", "hidden");
 
   // TODO(crbug/1308932): Remove toSkColor and make all SkColor4f.
-  if (Color(layer.background_color().toSkColor()).Alpha()) {
+  if (Color(layer.background_color().toSkColor()).Alpha() &&
+      ((flags & kLayerTreeIncludesDebugInfo) ||
+       // Omit backgroundColor for these layers because it's not interesting
+       // and we want to avoid platform differences and changes with CLs
+       // affecting backgroundColor in web tests that dump layer trees.
+       (debug_name != "Caret" && !debug_name.Contains("Scroll corner of")))) {
     json->SetString(
         "backgroundColor",
         Color(layer.background_color().toSkColor()).NameForLayoutTreeAsText());
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 61e25f9..d98d4ad7 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -229,6 +229,13 @@
       repainted.text_known_to_be_on_opaque_background) {
     return true;
   }
+  // Whether background color is transparent affects cc::Layers's contents
+  // opaque property.
+  if ((previous.background_color == Color()) !=
+      (repainted.background_color == Color())) {
+    return true;
+  }
+
   // |has_text| affects compositing decisions (see:
   // |PendingLayer::MergeInternal|).
   if (previous.has_text != repainted.has_text)
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index f9d6662..8dcda12 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
 
-#include "base/containers/adapters.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "cc/input/layer_selection_bound.h"
@@ -799,55 +798,6 @@
   return cc_list;
 }
 
-// The heuristic for picking a checkerboarding color works as follows:
-//   - During paint, PaintChunker will look for background color display items,
-//     and record the blending of background colors if the background is larger
-//     than a ratio of the chunk bounds.
-//   - After layer allocation, the paint chunks assigned to a layer are
-//     examined for a background color annotation.
-//   - The blending of background colors of chunks having background larger than
-//     a ratio of the layer is set as the layer's background color.
-//   - If the above color exists, it's also used as the safe opaque background
-//     color. Otherwise the color of the largest background is used, without the
-//     size requirement, as safe opaque background color should always get a
-//     value if possible.
-static void UpdateBackgroundColor(cc::Layer& layer,
-                                  const EffectPaintPropertyNode& layer_effect,
-                                  const PaintChunkSubset& paint_chunks) {
-  Vector<Color, 4> background_colors;
-  float min_background_area = kMinBackgroundColorCoverageRatio *
-                              layer.bounds().width() * layer.bounds().height();
-  for (auto it = paint_chunks.end(); it != paint_chunks.begin();) {
-    const auto& chunk = *(--it);
-    if (chunk.background_color == Color::kTransparent)
-      continue;
-    if (chunk.background_color_area >= min_background_area) {
-      Color chunk_background_color = chunk.background_color;
-      const auto& chunk_effect = chunk.properties.Effect().Unalias();
-      if (&chunk_effect != &layer_effect) {
-        if (chunk_effect.UnaliasedParent() != &layer_effect ||
-            !chunk_effect.IsOpacityOnly()) {
-          continue;
-        }
-        chunk_background_color =
-            chunk_background_color.CombineWithAlpha(chunk_effect.Opacity());
-      }
-      background_colors.push_back(chunk_background_color);
-      if (!chunk_background_color.HasAlpha()) {
-        // If this color is opaque, blending it with subsequent colors will have
-        // no effect.
-        break;
-      }
-    }
-  }
-
-  Color background_color;
-  for (Color color : base::Reversed(background_colors))
-    background_color = background_color.Blend(color);
-  // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
-  layer.SetBackgroundColor(SkColor4f::FromColor(background_color.Rgb()));
-}
-
 static void UpdateTouchActionRegion(
     const HitTestData& hit_test_data,
     const PropertyTreeState& layer_state,
@@ -1055,7 +1005,6 @@
     cc::Layer& layer,
     const PropertyTreeState& layer_state,
     const PaintChunkSubset& chunks) {
-  UpdateBackgroundColor(layer, layer_state.Effect(), chunks);
   UpdateTouchActionWheelEventHandlerAndNonFastScrollableRegions(
       layer, layer_state, chunks);
   UpdateRegionCaptureData(layer, layer_state, chunks);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
index ab922f5..551fda3c 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/graphics/compositing/pending_layer.h"
 
+#include "base/containers/adapters.h"
 #include "cc/layers/scrollbar_layer_base.h"
 #include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
 #include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
@@ -637,4 +638,46 @@
   return drawing && drawing->IsSolidColor();
 }
 
+// The heuristic for picking a checkerboarding color works as follows:
+// - During paint, PaintChunker will look for background color display items,
+//   and record the blending of background colors if the background is larger
+//   than a ratio of the chunk bounds.
+// - After layer allocation, the paint chunks assigned to a layer are examined
+//   for a background color annotation.
+// - The blending of background colors of chunks having background larger than
+//   a ratio of the layer is set as the layer's background color.
+SkColor4f PendingLayer::ComputeBackgroundColor() const {
+  Vector<Color, 4> background_colors;
+  float min_background_area =
+      kMinBackgroundColorCoverageRatio * bounds_.width() * bounds_.height();
+  for (auto it = chunks_.end(); it != chunks_.begin();) {
+    const auto& chunk = *(--it);
+    if (chunk.background_color == Color::kTransparent)
+      continue;
+    if (chunk.background_color_area >= min_background_area) {
+      Color chunk_background_color = chunk.background_color;
+      const auto& chunk_effect = chunk.properties.Effect().Unalias();
+      if (&chunk_effect != &property_tree_state_.Effect()) {
+        if (chunk_effect.UnaliasedParent() != &property_tree_state_.Effect() ||
+            !chunk_effect.IsOpacityOnly()) {
+          continue;
+        }
+        chunk_background_color =
+            chunk_background_color.CombineWithAlpha(chunk_effect.Opacity());
+      }
+      background_colors.push_back(chunk_background_color);
+      if (!chunk_background_color.HasAlpha()) {
+        // If this color is opaque, blending it with subsequent colors will have
+        // no effect.
+        break;
+      }
+    }
+  }
+
+  Color background_color;
+  for (Color color : base::Reversed(background_colors))
+    background_color = background_color.Blend(color);
+  return SkColor4f::FromColor(background_color.Rgb());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h
index adace2e..fc5ffd0 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.h
@@ -152,6 +152,8 @@
       scoped_refptr<const PaintArtifact> repainted_artifact,
       cc::LayerSelection&);
 
+  SkColor4f ComputeBackgroundColor() const;
+
  private:
   PendingLayer(const PaintChunkSubset&,
                const PaintChunk& first_chunk,
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index 0fe3037..b056ae8e 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -90,7 +90,9 @@
 
   if (GetType() != DisplayItem::kBoxDecorationBackground &&
       GetType() != DisplayItem::kDocumentBackground &&
-      GetType() != DisplayItem::kDocumentRootBackdrop)
+      GetType() != DisplayItem::kDocumentRootBackdrop &&
+      GetType() != DisplayItem::kCaret &&
+      GetType() != DisplayItem::kScrollCorner)
     return SK_ColorTRANSPARENT;
 
   if (!record_)
@@ -118,7 +120,7 @@
         item_rect = static_cast<const cc::DrawRRectOp*>(op)->rrect.rect();
         break;
       default:
-        continue;
+        return SK_ColorTRANSPARENT;
     }
     area = item_rect.width() * item_rect.height();
     return flags.getColor();
diff --git a/third_party/blink/renderer/platform/heap/heap_test_platform.h b/third_party/blink/renderer/platform/heap/heap_test_platform.h
index 7670cca6c..31382b1 100644
--- a/third_party/blink/renderer/platform/heap/heap_test_platform.h
+++ b/third_party/blink/renderer/platform/heap/heap_test_platform.h
@@ -43,9 +43,6 @@
   void OnCriticalMemoryPressure() final {
     platform_->OnCriticalMemoryPressure();
   }
-  bool OnCriticalMemoryPressure(size_t length) final {
-    return platform_->OnCriticalMemoryPressure(length);
-  }
   int NumberOfWorkerThreads() final {
     return platform_->NumberOfWorkerThreads();
   }
diff --git a/third_party/blink/renderer/platform/testing/test_paint_artifact.cc b/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
index 7254c06..fa41bed 100644
--- a/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
+++ b/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
@@ -104,6 +104,9 @@
           client.GetPaintInvalidationReason());
   paint_artifact_->RecordDebugInfo(client.Id(), client.DebugName(),
                                    client.OwnerNodeId());
+  auto& chunk = paint_artifact_->PaintChunks().back();
+  chunk.background_color = color;
+  chunk.background_color_area = bounds.size().GetArea();
   DidAddDisplayItem();
   return *this;
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index cece273..cac84c7 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1928,10 +1928,11 @@
 crbug.com/1147859 external/wpt/css/css-pseudo/highlight-painting-004.html [ Failure ]
 crbug.com/1295264 crbug.com/1147859 external/wpt/css/css-pseudo/highlight-painting-currentcolor-001.html [ Failure ]
 crbug.com/1295264 crbug.com/1147859 external/wpt/css/css-pseudo/highlight-painting-currentcolor-002.html [ Failure ]
-crbug.com/1341621 external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-visited-computed-001.html [ Failure ]
 crbug.com/1024156 external/wpt/css/css-pseudo/highlight-pseudos-inheritance-computed-001.html [ Failure ]
 crbug.com/1024156 external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-001.html [ Failure ]
 crbug.com/1024156 external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html [ Failure ]
+crbug.com/1024156 external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-003.html [ Failure ]
+crbug.com/1024156 external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-visited-computed-001.html [ Failure ]
 crbug.com/995106 external/wpt/css/css-pseudo/first-letter-exclude-inline-marker.html [ Failure ]
 crbug.com/995106 external/wpt/css/css-pseudo/first-letter-exclude-inline-child-marker.html [ Failure ]
 crbug.com/1172333 external/wpt/css/css-pseudo/first-letter-hi-001.html [ Failure ]
@@ -3241,7 +3242,8 @@
 crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-paired-cascade-006.html [ Pass ]
 crbug.com/1295264 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-001.html [ Pass ]
 crbug.com/1295264 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html [ Pass ]
-crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-visited-computed-001.html [ Failure ]
+crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-003.html [ Pass ]
+crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-visited-computed-001.html [ Pass ]
 crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-styling-002.html [ Pass ]
 crbug.com/1024156 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-styling-004.html [ Pass ]
 crbug.com/1309822 virtual/css-highlight-inheritance/external/wpt/css/css-pseudo/highlight-pseudos-inheritance-computed-001.html [ Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 4a97ffe..3d23cfbd 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1207,12 +1207,6 @@
     "args": ["--enable-features=CorsNonWildcardRequestHeadersSupport"]
   },
   {
-    "prefix": "enable-experimental-async-stack-tagging-api",
-    "platforms": ["Linux", "Mac", "Win"],
-    "bases": ["inspector-protocol/runtime"],
-    "args": ["--js-flags=--experimental-async-stack-tagging-api"]
-  },
-  {
     "prefix": "system-color-picker-appearance",
     "platforms": ["Linux", "Mac", "Win"],
     "bases": ["fast/forms/color-scheme/color/color-picker-appearance.html"],
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/iframe-srcdoc-history-inheritance.html b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/iframe-srcdoc-history-inheritance.html
index 52d460d..907c88e 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/iframe-srcdoc-history-inheritance.html
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/iframe-srcdoc-history-inheritance.html
@@ -40,9 +40,10 @@
 
   const promise = new Promise((resolve, reject) => {
     img.onload = resolve;
-    // First the security policy violation should be reported, which will finish
-    // this test. If for some reason the error event is fired without the
-    // violation being reported, something else went wrong—fail the test.
+    // If the img is blocked because of Content Security Policy, a violation
+    // should be reported first, and the test will fail. If for some other
+    // reason the error event is fired without the violation being reported,
+    // something else went wrong, hence the test should fail.
     img.error = e => {
       reject(new Error("The srcdoc iframe's img failed to load but not due to " +
                        "a CSP violation"));
@@ -52,8 +53,7 @@
         "new CSP. It means it was different and wasn't restored from history"));
     };
   });
-  // The srcdoc iframe tries to load an image, and should generate a security
-  // policy violation.
+  // The srcdoc iframe tries to load an image, which should succeed.
   img.src = "/common/square.png";
 
   return promise;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html
index 0d0da9e..5336aa1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-002.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>CSS Pseudo-Elements Test: highlight selectors getComputedStyle for currentcolor</title>
+<title>CSS Pseudo-Elements Test: implicit defaulting of ‘color’ in :root highlights</title>
 <link rel="help" href="https://drafts.csswg.org/css-pseudo/#highlight-selectors">
 <link rel="match" href="reference/highlight-pseudos-currentcolor-inheritance-computed-002-ref.html">
 <p>Pass if text below is green on lime, and the text itself represents green, not initial (black).</p>
@@ -9,7 +9,7 @@
 <style>
   main { color: green; }
   :root::selection { background-color: lime; }
-  :root::highlight(foo) { background-color: lime;}
+  :root::highlight(foo) { background-color: lime; }
 </style>
 <script>
   const [selection, highlight] = document.querySelectorAll("main");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-003.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-003.html
new file mode 100644
index 0000000..cd49802
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-currentcolor-inheritance-computed-003.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Pseudo-Elements Test: implicit defaulting of ‘color’ in :root highlights</title>
+<link rel="author" title="Delan Azabani" href="mailto:dazabani@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo/#highlight-selectors">
+<link rel="match" href="reference/highlight-pseudos-currentcolor-inheritance-computed-002-ref.html">
+<p>Pass if text below is green on lime, and the text itself represents green, not initial (black).</p>
+<main>FAIL</main>
+<main>FAIL</main>
+<style>
+  main { color: green; }
+  main::selection { background-color: lime; }
+  main::highlight(foo) { background-color: lime; }
+</style>
+<script>
+  const [selection, highlight] = document.querySelectorAll("main");
+
+  let selectionRange = new Range();
+  selectionRange.selectNode(selection);
+  window.getSelection().addRange(selectionRange);
+  selection.textContent = getComputedStyle(selection, "::selection").color;
+
+  let highlightRange = new Range();
+  highlightRange.selectNode(highlight);
+  CSS.highlights.set("foo", new Highlight(highlightRange));
+  highlight.textContent = getComputedStyle(highlight, "::highlight(foo)").color;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg-ref.html
new file mode 100644
index 0000000..1a0820c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<body style="margin: 0">
+Should be fully white, without any red.
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg.html
new file mode 100644
index 0000000..3796b09
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<link rel="help" href="https://crbug.com/1330509">
+<link rel="match" href="fractional-scale-gradient-bg-obscure-red-bg-ref.html">
+<style>
+  body {
+    background: red;
+    margin: 0;
+  }
+  .container {
+    width: 100vw;
+    height: 100vh;
+    background: white;
+  }
+  .transform {
+    transform-origin: 0 0;
+    will-change: transform;
+    background: linear-gradient(white, white);
+    width: 47px;
+    height: 47px;
+    position: absolute;
+  }
+</style>
+<div class="container">
+  Should be fully white, without any red.
+  <div class="transform" style="transform: scale(3.777)"></div>
+  <div class="transform" style="transform: scale(2.777)"></div>
+  <div class="transform" style="transform: scale(1.777)"></div>
+  <div class="transform" style="transform: scale(1.129)"></div>
+  <div class="transform" style="transform: scale(0.971)"></div>
+  <div class="transform" style="transform: scale(0.457)"></div>
+</div>
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index 5bc78dcc..244e921 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -19,7 +19,7 @@
       "name": "LayoutBlockFlow DIV class='scrollable bigBox'",
       "position": [1, 1],
       "bounds": [285, 800],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-above-fixed-1-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-above-fixed-1-expected.txt
index a9af6b1..f7a4893 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-above-fixed-1-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-above-fixed-1-expected.txt
@@ -22,7 +22,7 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true
+      "contentsOpaqueForText": true
     },
     {
       "name": "VerticalScrollbar",
@@ -64,7 +64,7 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
@@ -116,7 +116,7 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
@@ -168,7 +168,7 @@
       "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
index 39b564a..81f04838 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutBlockFlow DIV id='content'",
       "bounds": [285, 1000],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/background/background-resize-height-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/background/background-resize-height-expected.txt
index 035fff94..cf046380 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/background/background-resize-height-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/background/background-resize-height-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test image'",
       "position": [8, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 40, 60, 4]
@@ -20,7 +20,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test image size-contain'",
       "position": [108, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [0, 0, 60, 44],
         [50, 40, 60, 4]
@@ -30,7 +30,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test image percent-height'",
       "position": [208, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [0, 0, 60, 44],
         [50, 40, 60, 4]
@@ -40,7 +40,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test image bottom'",
       "position": [308, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -59,7 +59,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV class='test image repeat-round'",
       "bounds": [60, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "backfaceVisibility": "hidden",
       "invalidations": [
         [0, 0, 60, 44]
@@ -70,7 +70,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test generated'",
       "position": [8, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -100,7 +100,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test generated center'",
       "position": [358, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -110,7 +110,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='test generated repeat-space'",
       "position": [458, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring.js
deleted file mode 100644
index 2c25580..0000000
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring.js
+++ /dev/null
@@ -1,127 +0,0 @@
-(async function(testRunner) {
-  var {session, dp} = await testRunner.startBlank(
-      'Tests that async stack tagging API (recurring) works as expected.');
-
-  dp.Runtime.enable();
-  dp.Debugger.setAsyncCallStackDepth({maxDepth: 32});
-
-  const response1 = await dp.Runtime.onceExecutionContextCreated();
-  const pageContextId = response1.params.context.id;  // main page
-  session.evaluate(`
-    window.frame = document.createElement('iframe');
-    frame.src = '${testRunner.url('../resources/blank.html')}';
-    document.body.appendChild(frame);
-  `);
-  const response2 = await dp.Runtime.onceExecutionContextCreated();
-  const frameContextId = response2.params.context.id;  // IFrame
-
-  const apiEnabled = await dp.Runtime.evaluate(
-      {expression: `"scheduleAsyncTask" in console`, contextId: pageContextId});
-  if (!apiEnabled.result.result.value) {
-    testRunner.log('Skipping: async stack tagging API not enabled.');
-    testRunner.completeTest();
-    return;
-  }
-
-  const configs = [pageContextId, frameContextId];
-
-  dp.Runtime.onConsoleAPICalled((result) => testRunner.log(result));
-  dp.Runtime.onExceptionThrown((result) => testRunner.log(result));
-
-  const code = `
-  /* --- Runtime --- */
-
-  // Something akin to requestIdleCallback, but deterministic.
-
-  const BUDGET = 2;
-
-  function fakeRequestIdleCallback(cb) {
-    function makeDeadline() {
-      let ticks = BUDGET;
-
-      return {
-        ticksRemaining() {
-          return ticks--;
-        },
-      };
-    }
-
-    cb(makeDeadline());
-  }
-
-  /* --- Library --- */
-
-  function makeTask(id, name, jobs) {
-    return {
-      runNextJob() {
-        const f = jobs.shift();
-        console.startAsyncTask(id);
-        f();
-        console.finishAsyncTask(id);
-
-        if (jobs.length) {
-          return false;
-        }
-
-        console.cancelAsyncTask(id);
-        return true;
-      },
-    };
-  }
-
-  function makeScheduler() {
-    const tasks = [];
-
-    function workLoop(deadline) {
-      while (deadline.ticksRemaining() > 0 && tasks.length) {
-        const task = tasks[0];
-        const finished = task.runNextJob();
-        if (finished) {
-          tasks.shift();
-        }
-      }
-
-      if (tasks.length) {
-        fakeRequestIdleCallback(workLoop);
-        return;
-      }
-
-    }
-
-    return {
-      scheduleTask(name, jobs) {
-        const id = console.scheduleAsyncTask(name, true);
-        tasks.push(makeTask(id, name, jobs));
-      },
-
-      scheduleWorkLoop() {
-        fakeRequestIdleCallback(workLoop);
-      },
-    };
-  }
-
-  /* --- Userland --- */
-
-  function makeJob(i) {
-    return function someJob() {
-      console.trace(\`completeWork: job \${i}\`);
-    };
-  }
-
-  const scheduler = makeScheduler();
-
-  function businessLogic() {
-    scheduler.scheduleTask("fooTask", [makeJob(1), makeJob(2), makeJob(3)]);
-    scheduler.scheduleTask("barBask", [makeJob(4), makeJob(5)]);
-  }
-
-  businessLogic();
-  scheduler.scheduleWorkLoop();
-  `;
-
-  for (const contextId of configs) {
-    await dp.Runtime.evaluate({expression: code, contextId});
-  }
-
-  testRunner.completeTest();
-});
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api.js
deleted file mode 100644
index 6777966..0000000
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-api.js
+++ /dev/null
@@ -1,80 +0,0 @@
-(async function(testRunner) {
-  var {session, dp} = await testRunner.startBlank(
-      'Tests that async stack tagging API works as expected.');
-
-  dp.Runtime.enable();
-  dp.Debugger.setAsyncCallStackDepth({maxDepth: 32});
-
-  const response1 = await dp.Runtime.onceExecutionContextCreated();
-  const pageContextId = response1.params.context.id;  // main page
-  session.evaluate(`
-    window.frame = document.createElement('iframe');
-    frame.src = '${testRunner.url('../resources/blank.html')}';
-    document.body.appendChild(frame);
-  `);
-  const response2 = await dp.Runtime.onceExecutionContextCreated();
-  const frameContextId = response2.params.context.id;  // IFrame
-
-  const apiEnabled = await dp.Runtime.evaluate(
-      {expression: `"scheduleAsyncTask" in console`, contextId: pageContextId});
-  if (!apiEnabled.result.result.value) {
-    testRunner.log('Skipping: async stack tagging API not enabled.');
-    testRunner.completeTest();
-    return;
-  }
-
-  const configs = [pageContextId, frameContextId];
-
-  dp.Runtime.onConsoleAPICalled((result) => testRunner.log(result));
-  dp.Runtime.onExceptionThrown((result) => testRunner.log(result));
-
-  const code = `
-  /* --- Library --- */
-
-  function makeScheduler() {
-    let stack = [];
-
-    return {
-      scheduleUnitOfWork(f) {
-        const id = console.scheduleAsyncTask(f.name);
-        stack.push({ id, f });
-      },
-
-      workLoop() {
-        while (stack.length) {
-          const { id, f } = stack.pop();
-          console.startAsyncTask(id);
-          f();
-          console.finishAsyncTask(id);
-        }
-      },
-    };
-  }
-
-  /* --- Userland --- */
-
-  const scheduler = makeScheduler();
-
-  function someTask() {
-    console.trace("completeWork: someTask");
-  }
-
-  function someOtherTask() {
-    console.trace("completeWork: someOtherTask");
-  }
-
-  function businessLogic() {
-    scheduler.scheduleUnitOfWork(someTask);
-    scheduler.scheduleUnitOfWork(someOtherTask);
-  }
-
-  businessLogic();
-  scheduler.workLoop();
-  `;
-
-  for (const contextId of configs) {
-    await dp.Runtime.evaluate({expression: code, contextId});
-  }
-
-  testRunner.completeTest();
-});
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-collisions.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-collisions.js
deleted file mode 100644
index b19b64c..0000000
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-collisions.js
+++ /dev/null
@@ -1,95 +0,0 @@
-(async function(testRunner) {
-  var {session, dp} = await testRunner.startBlank(
-      'Tests that async stack tagging API deals with collisions as expected.');
-
-  dp.Runtime.enable();
-
-  const response1 = await dp.Runtime.onceExecutionContextCreated();
-  const pageContextId = response1.params.context.id;  // main page
-  session.evaluate(`
-    window.frame = document.createElement('iframe');
-    frame.src = '${testRunner.url('../resources/blank.html')}';
-    document.body.appendChild(frame);
-  `);
-  const response2 = await dp.Runtime.onceExecutionContextCreated();
-  const frameContextId = response2.params.context.id;  // IFrame
-
-  const apiEnabled = await dp.Runtime.evaluate(
-      {expression: `"scheduleAsyncTask" in console`, contextId: pageContextId});
-  if (!apiEnabled.result.result.value) {
-    testRunner.log('Skipping: async stack tagging API not enabled.');
-    testRunner.completeTest();
-    return;
-  }
-
-  const configs = [pageContextId, frameContextId];
-
-  dp.Runtime.onConsoleAPICalled((result) => testRunner.log(result));
-  dp.Runtime.onExceptionThrown((result) => testRunner.log(result));
-
-  const canReuseName = {
-    name: 'Scheduling async tasks with the same name should make different ids',
-    code: `
-      let id1 = console.scheduleAsyncTask("foo");
-      console.log(id1);
-      let id2 = console.scheduleAsyncTask("foo");
-      console.log(id2); // should not equal to id1
-      // cleanup
-      console.cancelAsyncTask(id1);
-      console.cancelAsyncTask(id2);
-      // check
-      id1 !== id2
-    `
-  };
-
-  const doesNotReuseIds = {
-    name: 'Cancelling async tasks does not end up reusing task ids',
-    code: `
-      let id1 = console.scheduleAsyncTask("A");
-      console.log(id1);
-      console.cancelAsyncTask(id1);
-      let id2 = console.scheduleAsyncTask("B");
-      console.log(id2); // should not equal to id1
-      console.cancelAsyncTask(id2);
-      // check
-      id1 !== id2
-    `
-  };
-
-  const doesNotCollideIds = {
-    name: 'Cancelling async tasks does not end up colliding task ids',
-    code: `
-      let id1 = console.scheduleAsyncTask("A");
-      console.log(id1);
-      let id2 = console.scheduleAsyncTask("B");
-      console.log(id2);
-      console.cancelAsyncTask(id1);
-      let id3 = console.scheduleAsyncTask("C");
-      console.log(id3); // should not equal to id2
-      // cleanup
-      console.cancelAsyncTask(id2);
-      console.cancelAsyncTask(id3);
-      // check
-      id1 !== id2 && id2 !== id3
-    `
-  };
-
-  const checks = [
-    canReuseName,
-    doesNotReuseIds,
-    doesNotCollideIds,
-  ];
-
-  for (const contextId of configs) {
-    for (const {name, code} of checks) {
-      testRunner.log(name);
-      let check =
-          await dp.Runtime.evaluate({expression: `{${code}}`, contextId});
-      if (!check.result.result.value) {
-        testRunner.fail(`Failed check: ${name}`);
-      }
-    }
-  }
-
-  testRunner.completeTest();
-});
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-errors.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-errors.js
deleted file mode 100644
index d27912b..0000000
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-errors.js
+++ /dev/null
@@ -1,162 +0,0 @@
-(async function(testRunner) {
-  var {session, dp} = await testRunner.startBlank(
-      'Tests that async stack tagging API errors out as expected.');
-
-  dp.Runtime.enable();
-
-  const response1 = await dp.Runtime.onceExecutionContextCreated();
-  const pageContextId = response1.params.context.id;  // main page
-  session.evaluate(`
-    window.frame = document.createElement('iframe');
-    frame.src = '${testRunner.url('../resources/blank.html')}';
-    document.body.appendChild(frame);
-  `);
-  const response2 = await dp.Runtime.onceExecutionContextCreated();
-  const frameContextId = response2.params.context.id;  // IFrame
-
-  const configs = [pageContextId, frameContextId];
-
-  dp.Runtime.onConsoleAPICalled((result) => testRunner.log(result));
-  dp.Runtime.onExceptionThrown((result) => testRunner.log(result));
-
-  const apiEnabled = await dp.Runtime.evaluate(
-      {expression: `"scheduleAsyncTask" in console`, contextId: pageContextId});
-  if (!apiEnabled.result.result.value) {
-    testRunner.log('Skipping: async stack tagging API not enabled.');
-    testRunner.completeTest();
-    return;
-  }
-
-  const failsScheduleWithNotEnoughArgs = {
-    name: 'Scheduling an async task with no argument should fail',
-    code: `
-      console.scheduleAsyncTask();
-    `
-  };
-
-  const failsScheduleWithBadRecurringArg = {
-    name: 'Scheduling an async task with a bad recurring flag should fail',
-    code: `
-      console.scheduleAsyncTask("foo", 42);
-    `
-  };
-
-  const failsScheduleWithTooManyArgs = {
-    name: 'Scheduling an async task with too many arguments should fail',
-    code: `
-      console.scheduleAsyncTask("foo", false, 42);
-    `
-  };
-
-  const failsStartWithBadTaskId = {
-    name: 'Starting an async task with an non-integer task id should fail',
-    code: `
-      console.startAsyncTask("wat");
-    `
-  };
-
-  const failsStartWithWrongTaskId = {
-    name: 'Starting an async task with an inexistent task id should fail',
-    code: `
-      console.startAsyncTask(100042);
-    `
-  };
-
-  const failsStopWithBadTaskId = {
-    name: 'Stopping an async task with an non-integer task id should fail',
-    code: `
-      console.stopAsyncTask("wat");
-    `
-  };
-
-  const failsStopWithWrongTaskId = {
-    name: 'Stopping an async task with an inexistent task id should fail',
-    code: `
-      console.stopAsyncTask(100042);
-    `
-  };
-
-  const failsCancelWithBadTaskId = {
-    name: 'Cancelling an async task with an non-integer task id should fail',
-    code: `
-      console.cancelAsyncTask("wat");
-    `
-  };
-
-  const failsCancelWithWrongTaskId = {
-    name: 'Cancelling an async task with an inexistent task id should fail',
-    code: `
-      console.cancelAsyncTask(100042);
-    `
-  };
-
-  const failsToStartAfterCancel = {
-    name: 'Starting a cancelled async task should fail',
-    code: `
-      let id = console.scheduleAsyncTask("cancel me");
-      console.log(id);
-      console.cancelAsyncTask(id);
-      console.startAsyncTask(id);
-    `
-  };
-
-  const failsToFinishAfterCancel = {
-    name: 'Finishing a cancelled async task should fail',
-    code: `
-      let id = console.scheduleAsyncTask("cancel me");
-      console.log(id);
-      console.startAsyncTask(id);
-      console.cancelAsyncTask(id);
-      console.finishAsyncTask(id);
-    `
-  };
-
-  const failsToCancelAfterFinish = {
-    name: 'Cancelling an already finished async task should fail',
-    code: `
-      let id = console.scheduleAsyncTask("cancel me");
-      console.log(id);
-      console.startAsyncTask(id);
-      console.finishAsyncTask(id);
-      console.cancelAsyncTask(id);
-    `
-  };
-
-  const failsToCancelAfterCancel = {
-    name: 'Cancelling an already cancelled async task should fail',
-    code: `
-      let id = console.scheduleAsyncTask("cancel me");
-      console.log(id);
-      console.cancelAsyncTask(id);
-      console.cancelAsyncTask(id);
-    `
-  };
-
-  const checks = [
-    failsScheduleWithNotEnoughArgs,
-    failsScheduleWithBadRecurringArg,
-    failsScheduleWithTooManyArgs,
-    failsStartWithBadTaskId,
-    failsStartWithWrongTaskId,
-    failsStopWithBadTaskId,
-    failsCancelWithBadTaskId,
-    failsCancelWithWrongTaskId,
-    failsStopWithWrongTaskId,
-    failsToStartAfterCancel,
-    failsToFinishAfterCancel,
-    failsToCancelAfterFinish,
-    failsToCancelAfterCancel,
-  ];
-
-  for (const contextId of configs) {
-    for (const {name, code} of checks) {
-      testRunner.log(name);
-      await dp.Runtime.evaluate({
-        expression: `try { ${code} } catch (e) { console.log(e.message); }`,
-        contextId
-      });
-    }
-  }
-
-  testRunner.completeTest();
-});
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-flag.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-flag.js
deleted file mode 100644
index 94b2d58..0000000
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-async-tagging-flag.js
+++ /dev/null
@@ -1,34 +0,0 @@
-(async function(testRunner) {
-  var {session, dp} = await testRunner.startBlank(
-      'Tests that async stack tagging API is disabled by default.');
-
-  dp.Runtime.enable();
-
-  const response1 = await dp.Runtime.onceExecutionContextCreated();
-  const pageContextId = response1.params.context.id;  // main page
-  session.evaluate(`
-    window.frame = document.createElement('iframe');
-    frame.src = '${testRunner.url('../resources/blank.html')}';
-    document.body.appendChild(frame);
-  `);
-  const response2 = await dp.Runtime.onceExecutionContextCreated();
-  const frameContextId = response2.params.context.id;  // IFrame
-
-  const configs = [pageContextId, frameContextId];
-
-  dp.Runtime.onConsoleAPICalled((result) => testRunner.log(result));
-  dp.Runtime.onExceptionThrown((result) => testRunner.log(result));
-
-  const code = `
-    console.log(typeof console.scheduleAsyncTask);
-    console.log(typeof console.startAsyncTask);
-    console.log(typeof console.finishAsyncTask);
-    console.log(typeof console.cancelAsyncTask);
-  `;
-
-  for (const contextId of configs) {
-    await dp.Runtime.evaluate({expression: code, contextId});
-  }
-
-  testRunner.completeTest();
-});
diff --git a/third_party/blink/web_tests/loader/preload-media-crash.html b/third_party/blink/web_tests/loader/preload-media-crash.html
new file mode 100644
index 0000000..f02f3e2dd
--- /dev/null
+++ b/third_party/blink/web_tests/loader/preload-media-crash.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<link rel="manifest" href="dummy.xml" id="link">
+<script>
+  const element = document.getElementById("link");
+
+  async function test() {
+      await new Promise(resolve => setTimeout(resolve, 100));
+      element.setAttribute("disabled", "");
+      await new Promise(resolve => setTimeout(resolve, 100));
+      element.setAttribute("media", "projection");
+      await new Promise(resolve => setTimeout(resolve, 100));
+      testRunner.notifyDone();
+  }
+
+  if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+  }
+
+  test();
+
+</script>
+
+<body>
+This test should not crash.
+</body>
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
index 2d91714..2dd11e1 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
index caa80130..2dd11e1 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
index 90559b3..2dd11e1 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
index 1a8b4f10..2dd11e1 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/generic/compositing/squashing/squash-above-fixed-1-expected.txt b/third_party/blink/web_tests/platform/generic/compositing/squashing/squash-above-fixed-1-expected.txt
index 0bf1093..aa121b1 100644
--- a/third_party/blink/web_tests/platform/generic/compositing/squashing/squash-above-fixed-1-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/compositing/squashing/squash-above-fixed-1-expected.txt
@@ -22,7 +22,7 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true
+      "contentsOpaqueForText": true
     },
     {
       "name": "VerticalScrollbar",
@@ -64,7 +64,7 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
@@ -116,7 +116,7 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
@@ -168,7 +168,7 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt
deleted file mode 100644
index 8b205c7..0000000
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that async stack tagging API works as expected.
-Skipping: async stack tagging API not enabled.
-
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt
deleted file mode 100644
index 9972365..0000000
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that async stack tagging API (recurring) works as expected.
-Skipping: async stack tagging API not enabled.
-
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt
deleted file mode 100644
index 6cc7644..0000000
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that async stack tagging API deals with collisions as expected.
-Skipping: async stack tagging API not enabled.
-
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt
deleted file mode 100644
index 7316361b..0000000
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that async stack tagging API errors out as expected.
-Skipping: async stack tagging API not enabled.
-
diff --git a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt b/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt
deleted file mode 100644
index 9a6dbaf..0000000
--- a/third_party/blink/web_tests/platform/generic/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt
+++ /dev/null
@@ -1,210 +0,0 @@
-Tests that async stack tagging API is disabled by default.
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 1
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 3
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 1
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 3
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : undefined
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/generic/loader/preload-media-crash-expected.txt b/third_party/blink/web_tests/platform/generic/loader/preload-media-crash-expected.txt
new file mode 100644
index 0000000..fc0660cf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/loader/preload-media-crash-expected.txt
@@ -0,0 +1 @@
+This test should not crash.
diff --git a/third_party/blink/web_tests/platform/generic/paint/invalidation/background/background-resize-height-expected.txt b/third_party/blink/web_tests/platform/generic/paint/invalidation/background/background-resize-height-expected.txt
index 4e5e2f9..28ab19d7 100644
--- a/third_party/blink/web_tests/platform/generic/paint/invalidation/background/background-resize-height-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/paint/invalidation/background/background-resize-height-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test image'",
       "position": [8, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 40, 60, 4]
@@ -20,7 +20,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test image size-contain'",
       "position": [108, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [0, 0, 60, 44],
         [50, 40, 60, 4]
@@ -30,7 +30,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test image percent-height'",
       "position": [208, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [0, 0, 60, 44],
         [50, 40, 60, 4]
@@ -40,7 +40,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test image bottom'",
       "position": [308, 8],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -59,7 +59,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='test image repeat-round'",
       "bounds": [60, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "backfaceVisibility": "hidden",
       "invalidations": [
         [0, 0, 60, 44]
@@ -70,7 +70,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test generated'",
       "position": [8, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -100,7 +100,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test generated center'",
       "position": [358, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
@@ -110,7 +110,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test generated repeat-space'",
       "position": [458, 108],
       "bounds": [110, 44],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "invalidations": [
         [50, 0, 60, 44],
         [0, 0, 60, 44]
diff --git a/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/composited-svg-expected.txt b/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/composited-svg-expected.txt
index a549b1d7..87521e5 100644
--- a/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/composited-svg-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/composited-svg-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutSVGRect rect id='rect'",
       "position": [10, 10],
       "bounds": [100, 100],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt b/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt
index ef8f7c2..e72b1c66 100644
--- a/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutSVGRoot svg",
       "position": [50, 0],
       "bounds": [500, 400],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt
deleted file mode 100644
index a39917f2..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-expected.txt
+++ /dev/null
@@ -1,266 +0,0 @@
-Tests that async stack tagging API works as expected.
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: someOtherTask
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : someOtherTask
-                    lineNumber : 32
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 10
-                    functionName : workLoop
-                    lineNumber : 16
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 41
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleUnitOfWork
-                        lineNumber : 8
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 37
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 40
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : someOtherTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: someTask
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : someTask
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 10
-                    functionName : workLoop
-                    lineNumber : 16
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 41
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleUnitOfWork
-                        lineNumber : 8
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 36
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 40
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : someTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: someOtherTask
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : someOtherTask
-                    lineNumber : 32
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 10
-                    functionName : workLoop
-                    lineNumber : 16
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 41
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleUnitOfWork
-                        lineNumber : 8
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 37
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 40
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : someOtherTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: someTask
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : someTask
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 10
-                    functionName : workLoop
-                    lineNumber : 16
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 41
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleUnitOfWork
-                        lineNumber : 8
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 36
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 40
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : someTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt
deleted file mode 100644
index 4cf0e360..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-api-recurring-expected.txt
+++ /dev/null
@@ -1,984 +0,0 @@
-Tests that async stack tagging API (recurring) works as expected.
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 1
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 2
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 3
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 4
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 84
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : barBask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 5
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [8] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [9] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 84
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : barBask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 1
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 2
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 3
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 83
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : fooTask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 4
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 84
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : barBask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : completeWork: job 5
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : someJob
-                    lineNumber : 76
-                    scriptId : <string>
-                    url : 
-                }
-                [1] : {
-                    columnNumber : 8
-                    functionName : runNextJob
-                    lineNumber : 28
-                    scriptId : <string>
-                    url : 
-                }
-                [2] : {
-                    columnNumber : 30
-                    functionName : workLoop
-                    lineNumber : 47
-                    scriptId : <string>
-                    url : 
-                }
-                [3] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [4] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [5] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [6] : {
-                    columnNumber : 8
-                    functionName : workLoop
-                    lineNumber : 54
-                    scriptId : <string>
-                    url : 
-                }
-                [7] : {
-                    columnNumber : 4
-                    functionName : fakeRequestIdleCallback
-                    lineNumber : 18
-                    scriptId : <string>
-                    url : 
-                }
-                [8] : {
-                    columnNumber : 8
-                    functionName : scheduleWorkLoop
-                    lineNumber : 67
-                    scriptId : <string>
-                    url : 
-                }
-                [9] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 88
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 27
-                        functionName : scheduleTask
-                        lineNumber : 62
-                        scriptId : <string>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 14
-                        functionName : businessLogic
-                        lineNumber : 84
-                        scriptId : <string>
-                        url : 
-                    }
-                    [2] : {
-                        columnNumber : 2
-                        functionName : 
-                        lineNumber : 87
-                        scriptId : <string>
-                        url : 
-                    }
-                ]
-                description : barBask
-            }
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt
deleted file mode 100644
index fd321df..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-collisions-expected.txt
+++ /dev/null
@@ -1,386 +0,0 @@
-Tests that async stack tagging API deals with collisions as expected.
-Scheduling async tasks with the same name should make different ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 0
-                type : number
-                value : 0
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 1
-                type : number
-                value : 1
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling async tasks does not end up reusing task ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 2
-                type : number
-                value : 2
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 3
-                type : number
-                value : 3
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling async tasks does not end up colliding task ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 4
-                type : number
-                value : 4
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 5
-                type : number
-                value : 5
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 6
-                type : number
-                value : 6
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 7
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling async tasks with the same name should make different ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 7
-                type : number
-                value : 7
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 8
-                type : number
-                value : 8
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling async tasks does not end up reusing task ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 9
-                type : number
-                value : 9
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling async tasks does not end up colliding task ids
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 11
-                type : number
-                value : 11
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 12
-                type : number
-                value : 12
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 13
-                type : number
-                value : 13
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 7
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt
deleted file mode 100644
index 4fcf16a..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-errors-expected.txt
+++ /dev/null
@@ -1,920 +0,0 @@
-Tests that async stack tagging API errors out as expected.
-Scheduling an async task with no argument should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling an async task with a bad recurring flag should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling an async task with too many arguments should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task ID should be an integer
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Stopping an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.stopAsyncTask is not a function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task ID should be an integer
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Stopping an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.stopAsyncTask is not a function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting a cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 0
-                type : number
-                value : 0
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Finishing a cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 1
-                type : number
-                value : 1
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 6
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an already finished async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 2
-                type : number
-                value : 2
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 6
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an already cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 3
-                type : number
-                value : 3
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling an async task with no argument should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling an async task with a bad recurring flag should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Scheduling an async task with too many arguments should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Unexpected arguments
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task ID should be an integer
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Stopping an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.stopAsyncTask is not a function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an async task with an non-integer task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task ID should be an integer
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Stopping an async task with an inexistent task id should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.stopAsyncTask is not a function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Starting a cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 4
-                type : number
-                value : 4
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Finishing a cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 5
-                type : number
-                value : 5
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 6
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an already finished async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 6
-                type : number
-                value : 6
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 6
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Cancelling an already cancelled async task should fail
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 7
-                type : number
-                value : 7
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 14
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : Task with ID doesn't exist
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 27
-                    functionName : 
-                    lineNumber : 5
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt
deleted file mode 100644
index fcf2ca02..0000000
--- a/third_party/blink/web_tests/platform/generic/virtual/enable-experimental-async-stack-tagging-api/inspector-protocol/runtime/runtime-console-async-tagging-flag-expected.txt
+++ /dev/null
@@ -1,210 +0,0 @@
-Tests that async stack tagging API is disabled by default.
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 1
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 3
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 1
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 3
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : function
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 12
-                    functionName : 
-                    lineNumber : 4
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
index 800944c..705559a 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
index b9346e2..ce7545ad 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
index 72ea3435..d8fc1c9 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index 0610a1b1..70a80bad 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
index 12ef2ff7..708e9e8b 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
index a4546b7c..7295bb3 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
index 492c774..42b00ad9 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
index 4cf54316..841e639 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/yuv-decode-eligible/color-profile-layer-expected.png b/third_party/blink/web_tests/platform/linux/images/yuv-decode-eligible/color-profile-layer-expected.png
index 336fd08..a4fdd58 100644
--- a/third_party/blink/web_tests/platform/linux/images/yuv-decode-eligible/color-profile-layer-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/yuv-decode-eligible/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/yuv-decode-eligible/color-profile-layer-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/yuv-decode-eligible/color-profile-layer-expected.png
index f1946db..871c6962 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/yuv-decode-eligible/color-profile-layer-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/yuv-decode-eligible/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
index 3f1963f..28ca04a2 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutNGBlockFlow DIV id='content'",
       "bounds": [285, 1000],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..2d7844c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..2d7844c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
new file mode 100644
index 0000000..94016c7e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
new file mode 100644
index 0000000..d82feba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
new file mode 100644
index 0000000..9d94d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
new file mode 100644
index 0000000..f9cd12f4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..2d7844c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
new file mode 100644
index 0000000..94016c7e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
new file mode 100644
index 0000000..551ffe9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
new file mode 100644
index 0000000..9d94d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
new file mode 100644
index 0000000..f9cd12f4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..f38ebae5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
new file mode 100644
index 0000000..94016c7e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
new file mode 100644
index 0000000..d82feba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
new file mode 100644
index 0000000..9d94d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
new file mode 100644
index 0000000..f9cd12f4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..2d7844c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac11/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
new file mode 100644
index 0000000..94016c7e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
new file mode 100644
index 0000000..551ffe9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
new file mode 100644
index 0000000..9d94d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
new file mode 100644
index 0000000..f9cd12f4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..f38ebae5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index fd67972f..c955d3e 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -19,7 +19,7 @@
       "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
       "position": [1, 1],
       "bounds": [285, 800],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
index ab44ca2..1c6265e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -21,7 +21,7 @@
     {
       "name": "LayoutNGBlockFlow DIV id='content'",
       "bounds": [285, 1000],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index f58d14c..94016c7e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
index 26b563f..d82feba 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
index 8173aa9..9d94d95 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
index 18fbcb2..f9cd12f4 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
index ac9a5a4..2d7844c 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index 7cd40bc..3cfef88 100644
--- a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -19,7 +19,7 @@
       "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
       "position": [1, 1],
       "bounds": [285, 800],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/platform/win/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
index 3f1963f..28ca04a2 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
+++ b/third_party/blink/web_tests/platform/win/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutNGBlockFlow DIV id='content'",
       "bounds": [285, 1000],
-      "contentsOpaque": true,
+      "contentsOpaqueForText": true,
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
index 6069802..9da068a7 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
index 59e24c6..f0bf0c21 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index 7de056c9..e985d8f 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
index 59a35be..9da9cee 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
index 28825b5..54641f8 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
index ad5618ea..b34df05 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
index 8639f69..5f8f72c 100644
--- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
new file mode 100644
index 0000000..9da068a7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-grammar-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
new file mode 100644
index 0000000..f0bf0c21
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-line-spelling-error-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
new file mode 100644
index 0000000..3d489455
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
new file mode 100644
index 0000000..0f5cb1bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
new file mode 100644
index 0000000..e985d8f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
new file mode 100644
index 0000000..9da9cee
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
new file mode 100644
index 0000000..54641f8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
new file mode 100644
index 0000000..b34df05
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
new file mode 100644
index 0000000..5f8f72c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win10/fast/css3-text/css3-text-decoration/text-decoration-style-wavy-font-size-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-position-inline-001.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-position-inline-001.html
new file mode 100644
index 0000000..b5b039e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-position-inline-001.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/#propdef-anchor-name">
+<link rel="author" href="mailto:kojii@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<style>
+#container {
+  position: relative;
+  font-family: Ahem;
+  font-size: 10px;
+  line-height: 1;
+  width: 10em;
+}
+#anchor1 {
+  anchor-name: --a1;
+}
+.target {
+  position: absolute;
+}
+</style>
+<body onload="checkLayout('.target')">
+  <div id="container">
+    <div>
+      0123<span id="anchor1">456</span>78</span>
+    </div>
+
+    <div class="target" style="left: anchor(--a1 left)" data-offset-x=40></div>
+    <div class="target" style="right: anchor(--a1 right)" data-offset-x=70></div>
+    <div class="target" style="top: anchor(--a1 top)" data-offset-y=0></div>
+    <div class="target" style="bottom: anchor(--a1 bottom)" data-offset-y=10></div>
+  </div>
+</body>
diff --git a/third_party/closure_compiler/externs/passwords_private.js b/third_party/closure_compiler/externs/passwords_private.js
index 470ec577..42d1e34 100644
--- a/third_party/closure_compiler/externs/passwords_private.js
+++ b/third_party/closure_compiler/externs/passwords_private.js
@@ -119,6 +119,16 @@
 
 /**
  * @typedef {{
+ *   compromiseTime: number,
+ *   elapsedTimeSinceCompromise: string,
+ *   compromiseType: !chrome.passwordsPrivate.CompromiseType,
+ *   isMuted: boolean
+ * }}
+ */
+chrome.passwordsPrivate.CompromisedInfo;
+
+/**
+ * @typedef {{
  *   urls: !chrome.passwordsPrivate.UrlCollection,
  *   username: string,
  *   password: (string|undefined),
@@ -126,7 +136,10 @@
  *   id: number,
  *   storedIn: !chrome.passwordsPrivate.PasswordStoreSet,
  *   isAndroidCredential: boolean,
- *   note: string
+ *   note: string,
+ *   changePasswordUrl: (string|undefined),
+ *   hasStartableScript: boolean,
+ *   compromisedInfo: (!chrome.passwordsPrivate.CompromisedInfo|undefined)
  * }}
  */
 chrome.passwordsPrivate.PasswordUiEntry;
@@ -149,30 +162,6 @@
 
 /**
  * @typedef {{
- *   compromiseTime: number,
- *   elapsedTimeSinceCompromise: string,
- *   compromiseType: !chrome.passwordsPrivate.CompromiseType,
- *   isMuted: boolean
- * }}
- */
-chrome.passwordsPrivate.CompromisedInfo;
-
-/**
- * @typedef {{
- *   urls: !chrome.passwordsPrivate.UrlCollection,
- *   id: number,
- *   isAndroidCredential: boolean,
- *   changePasswordUrl: (string|undefined),
- *   hasStartableScript: boolean,
- *   username: string,
- *   password: (string|undefined),
- *   compromisedInfo: (!chrome.passwordsPrivate.CompromisedInfo|undefined)
- * }}
- */
-chrome.passwordsPrivate.InsecureCredential;
-
-/**
- * @typedef {{
  *   state: !chrome.passwordsPrivate.PasswordCheckState,
  *   alreadyProcessed: (number|undefined),
  *   remainingInQueue: (number|undefined),
@@ -323,53 +312,22 @@
 
 /**
  * Requests the latest compromised credentials.
- * @param {function(!Array<!chrome.passwordsPrivate.InsecureCredential>): void}
+ * @param {function(!Array<!chrome.passwordsPrivate.PasswordUiEntry>): void}
  *     callback
  */
 chrome.passwordsPrivate.getCompromisedCredentials = function(callback) {};
 
 /**
  * Requests the latest weak credentials.
- * @param {function(!Array<!chrome.passwordsPrivate.InsecureCredential>): void}
+ * @param {function(!Array<!chrome.passwordsPrivate.PasswordUiEntry>): void}
  *     callback
  */
 chrome.passwordsPrivate.getWeakCredentials = function(callback) {};
 
 /**
- * Requests the plaintext password for |credential|. |callback| gets invoked
- * with the same |credential|, whose |password| field will be set.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential The insecure
- *     credential whose password is being retrieved.
- * @param {!chrome.passwordsPrivate.PlaintextReason} reason The reason why the
- *     plaintext password is requested.
- * @param {function(!chrome.passwordsPrivate.InsecureCredential): void} callback
- *     The callback that gets invoked with the result.
- */
-chrome.passwordsPrivate.getPlaintextInsecurePassword = function(credential, reason, callback) {};
-
-/**
- * Requests to change the password of |credential| to |new_password|. Invokes
- * |callback| or raises an error depending on whether the operation succeeded.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential The
- *     credential whose password should be changed.
- * @param {string} new_password The new password.
- * @param {function(): void=} callback The callback that gets invoked in the
- *     end.
- */
-chrome.passwordsPrivate.changeInsecureCredential = function(credential, new_password, callback) {};
-
-/**
- * Requests to remove |credential| from the password store. Invokes |callback|
- * on completion.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential
- * @param {function(): void=} callback
- */
-chrome.passwordsPrivate.removeInsecureCredential = function(credential, callback) {};
-
-/**
  * Requests to mute |credential| from the password store. Invokes |callback| on
  * completion.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential
+ * @param {!chrome.passwordsPrivate.PasswordUiEntry} credential
  * @param {function(): void=} callback
  */
 chrome.passwordsPrivate.muteInsecureCredential = function(credential, callback) {};
@@ -377,15 +335,15 @@
 /**
  * Requests to unmute |credential| from the password store. Invokes |callback|
  * on completion.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential
+ * @param {!chrome.passwordsPrivate.PasswordUiEntry} credential
  * @param {function(): void=} callback
  */
 chrome.passwordsPrivate.unmuteInsecureCredential = function(credential, callback) {};
 
 /**
  * Records that a change password flow was started for |credential|.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential The
- *     credential for which the flow was triggered.
+ * @param {!chrome.passwordsPrivate.PasswordUiEntry} credential The credential
+ *     for which the flow was triggered.
  * @param {boolean} isManualFlow
  * @param {function(): void=} callback
  */
@@ -421,7 +379,7 @@
  * Starts an automated password change for |credential|. Invokes |callback| on
  * completion with a boolean parameter that signals whether the credential was
  * changed successfully.
- * @param {!chrome.passwordsPrivate.InsecureCredential} credential
+ * @param {!chrome.passwordsPrivate.PasswordUiEntry} credential
  * @param {function(boolean): void=} callback
  */
 chrome.passwordsPrivate.startAutomatedPasswordChange = function(credential, callback) {};
diff --git a/third_party/openh264/BUILD.gn b/third_party/openh264/BUILD.gn
index a8c658b..a858b368 100644
--- a/third_party/openh264/BUILD.gn
+++ b/third_party/openh264/BUILD.gn
@@ -12,7 +12,7 @@
   cflags = []
   defines = []
 
-  if (is_chromeos_ash && current_cpu == "arm") {
+  if (is_chromeos && current_cpu == "arm") {
     # HAVE_NEON and __chromeos__ are needed for enabling NEON on ChromeOS
     # devices.
     defines += [
@@ -131,7 +131,7 @@
 
 source_set("common") {
   sources = openh264_common_sources
-  if (is_chromeos_ash && current_cpu == "arm") {
+  if (is_chromeos && current_cpu == "arm") {
     sources += openh264_common_sources_asm_arm
   }
   include_dirs = openh264_common_include_dirs
@@ -157,7 +157,7 @@
 
 source_set("processing") {
   sources = openh264_processing_sources
-  if (is_chromeos_ash && current_cpu == "arm") {
+  if (is_chromeos && current_cpu == "arm") {
     sources += openh264_processing_sources_asm_arm
   }
   include_dirs = openh264_processing_include_dirs
@@ -174,7 +174,7 @@
 
 source_set("encoder") {
   sources = openh264_encoder_sources
-  if (is_chromeos_ash && current_cpu == "arm") {
+  if (is_chromeos && current_cpu == "arm") {
     sources += openh264_encoder_sources_asm_arm
   }
   include_dirs = openh264_encoder_include_dirs
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8dbde950..f37eee1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -40881,6 +40881,8 @@
   <int value="4310" label="SendBeaconWithUSVString"/>
   <int value="4311" label="ReplacedElementPaintedWithOverflow"/>
   <int value="4312" label="ImageAd"/>
+  <int value="4313" label="LinkRelPrefetchAsDocumentSameOrigin"/>
+  <int value="4314" label="LinkRelPrefetchAsDocumentCrossOrigin"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index b962464..a504a41 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -572,7 +572,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosLargeCursor" enum="BooleanEnabled"
-    expires_after="2022-11-21">
+    expires_after="2023-01-22">
   <owner>dtseng@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -594,7 +594,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosScreenMagnifier" enum="BooleanEnabled"
-    expires_after="2022-11-18">
+    expires_after="2023-01-22">
   <owner>dtseng@chromium.org</owner>
   <owner>josiahk@google.com</owner>
   <owner>kenjibaheux@google.com</owner>
@@ -1338,7 +1338,7 @@
 </histogram>
 
 <histogram name="Accessibility.Performance.HandleAXEvents" units="ms"
-    expires_after="2022-11-18">
+    expires_after="2023-01-22">
   <owner>aleventhal@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml
index e43f67ac..8f3e2e61 100644
--- a/tools/metrics/histograms/metadata/apps/histograms.xml
+++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -997,7 +997,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.SortDiscoveryDurationAfterEducationNudge"
-    units="ms" expires_after="2023-01-15">
+    units="ms" expires_after="2023-01-22">
   <owner>andrewxu@chromium.org</owner>
   <owner>tbarzic@chromium.org</owner>
   <summary>
@@ -1538,7 +1538,7 @@
 </histogram>
 
 <histogram name="Apps.AppListPageSwitcherSource"
-    enum="AppListPageSwitcherSource" expires_after="2022-11-13">
+    enum="AppListPageSwitcherSource" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="TabletOrClamshellMode" -->
 
   <owner>tbarzic@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 9366a4b..6bc1d15a 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -290,7 +290,7 @@
   </summary>
 </histogram>
 
-<histogram name="Arc.AppCount" units="units" expires_after="2023-01-15">
+<histogram name="Arc.AppCount" units="units" expires_after="2023-01-22">
   <owner>elijahtaylor@google.com</owner>
   <owner>fahdi@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index e55c2d4..b985041 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -1240,7 +1240,7 @@
 </histogram>
 
 <histogram name="Ash.CaptureModeController.ScreenshotsPerWeek" units="int"
-    expires_after="2022-11-13">
+    expires_after="2023-01-22">
   <owner>afakhry@chromium.org</owner>
   <owner>gzadina@google.com</owner>
   <summary>
@@ -2012,7 +2012,7 @@
 </histogram>
 
 <histogram name="Ash.DeskTemplate.NewTemplate" enum="BooleanHit"
-    expires_after="2022-11-22">
+    expires_after="2023-01-22">
   <owner>avynn@google.com</owner>
   <owner>janetmac@chromium.org</owner>
   <summary>
@@ -2957,7 +2957,7 @@
 </histogram>
 
 <histogram name="Ash.Notification.ExpandOrCollapse.AnimationSmoothness"
-    units="%" expires_after="2022-11-20">
+    units="%" expires_after="2023-01-22">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -5043,7 +5043,7 @@
 </histogram>
 
 <histogram name="Ash.WindowDragFromShelfResult" enum="ShelfWindowDragResult"
-    expires_after="2022-10-30">
+    expires_after="2023-01-22">
   <owner>andrewxu@chromium.org</owner>
   <owner>tbarzic@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index b07e2fa8..1afd9e5 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -49,7 +49,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.Accessibility.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -551,7 +551,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.CompositingCommit.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -574,7 +574,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.CompositingInputs.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -597,7 +597,7 @@
 </histogram>
 
 <histogram name="Blink.Compression.CompressionStream.Format"
-    enum="CompressionStreamsFormat" expires_after="2022-11-20">
+    enum="CompressionStreamsFormat" expires_after="2023-01-22">
   <owner>ricea@chromium.org</owner>
   <owner>yhirano@chromium.org</owner>
   <summary>
@@ -609,7 +609,7 @@
 </histogram>
 
 <histogram name="Blink.Compression.DecompressionStream.Format"
-    enum="CompressionStreamsFormat" expires_after="2022-11-20">
+    enum="CompressionStreamsFormat" expires_after="2023-01-22">
   <owner>ricea@chromium.org</owner>
   <owner>yhirano@chromium.org</owner>
   <summary>
@@ -621,7 +621,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ContentDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -1373,7 +1373,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.HitTestDocumentUpdate.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -1716,7 +1716,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ImplCompositorCommit.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -1872,7 +1872,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.Layout.UpdateTime" units="microseconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -2188,7 +2188,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ParseStyleSheet.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
@@ -3170,7 +3170,7 @@
 </histogram>
 
 <histogram name="Blink.UseCounter.UserAgentOverride" enum="UserAgentOverride"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>aarontag@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -3298,7 +3298,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.WaitForCommit.UpdateTime"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" -->
 
 <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" -->
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
index 451b6e5..9c053066 100644
--- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml
+++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -654,7 +654,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.FastPair.PairDevice.ErrorReason"
-    enum="BluetoothDeviceConnectErrorCode" expires_after="2022-09-20">
+    enum="BluetoothDeviceConnectErrorCode" expires_after="2023-01-22">
   <owner>shanefitz@google.com</owner>
   <owner>julietlevesque@google.com</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -750,7 +750,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.FastPair.Passkey.Decrypt.Result"
-    enum="BooleanSuccess" expires_after="2022-09-20">
+    enum="BooleanSuccess" expires_after="2023-01-22">
   <owner>shanefitz@google.com</owner>
   <owner>julietlevesque@google.com</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -959,7 +959,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.FastPair.TotalGattConnectionTime"
-    units="ms" expires_after="2022-09-20">
+    units="ms" expires_after="2023-01-22">
   <owner>shanefitz@google.com</owner>
   <owner>julietlevesque@google.com</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/bookmarks/histograms.xml b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
index fab6f04..82cb06eb 100644
--- a/tools/metrics/histograms/metadata/bookmarks/histograms.xml
+++ b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
@@ -130,7 +130,7 @@
 </histogram>
 
 <histogram name="Bookmarks.Count.OnProfileLoad" units="bookmarks"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>supertri@chromium.org</owner>
   <owner>isherman@chromium.org</owner>
   <owner>aidanday@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index 5d12f6c..bc9545d 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -956,7 +956,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Intents.IntentPickerAction"
-    enum="IntentPickerDialogAction" expires_after="2023-01-15">
+    enum="IntentPickerDialogAction" expires_after="2023-01-22">
   <owner>tsergeant@chromium.org</owner>
   <owner>chromeos-apps-foundation-team@google.com</owner>
   <summary>
@@ -1360,7 +1360,7 @@
 </histogram>
 
 <histogram name="ChromeOS.MessageCenter.ScrollActionReason"
-    enum="ChromeOSMessageCenterScrollActionReason" expires_after="2022-11-22">
+    enum="ChromeOSMessageCenterScrollActionReason" expires_after="2023-01-22">
   <owner>yoshiki@chromium.org</owner>
   <owner>omrilio@chromium.org</owner>
   <owner>leandre@chromium.org</owner>
@@ -1490,7 +1490,7 @@
 </histogram>
 
 <histogram name="ChromeOS.SAML.Scraping.PasswordCountAll" units="passwords"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mslus@chromium.org</owner>
   <owner>emaxx@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
index 79ccb796..3cc0d976 100644
--- a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
@@ -408,7 +408,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.WindowOpenDuration" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-customization@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index 76de164b..4a06c65 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -368,7 +368,7 @@
 
 <histogram
     name="Compositing.Display.OverlayProcessorUsingStrategy.CheckOverlaySupportCallCount"
-    units="units" expires_after="2022-11-20">
+    units="units" expires_after="2023-01-22">
   <owner>khaslett@chromium.org</owner>
   <owner>kylechar@chromium.org</owner>
   <summary>
@@ -379,7 +379,7 @@
 
 <histogram
     name="Compositing.Display.OverlayProcessorUsingStrategy.CheckOverlaySupportUs"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
   <owner>khaslett@chromium.org</owner>
   <owner>kylechar@chromium.org</owner>
   <summary>
@@ -517,7 +517,7 @@
 </histogram>
 
 <histogram name="Compositing.Renderer.CALayer.OddOffsetVideo" enum="OddOffset"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>magchen@chromium.org</owner>
   <owner>ccameron@chromium.org</owner>
   <summary>
@@ -527,7 +527,7 @@
 </histogram>
 
 <histogram name="Compositing.Renderer.CALayer.OddSizedVideo" enum="OddSize"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>magchen@chromium.org</owner>
   <owner>ccameron@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index f20b05f..7f9cc8f 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -519,7 +519,7 @@
 </histogram>
 
 <histogram name="ContentSettings.Popups.BlockerActions"
-    enum="PopupBlockerAction" expires_after="2022-11-20">
+    enum="PopupBlockerAction" expires_after="2023-01-22">
   <owner>csharrison@chromium.org</owner>
   <owner>lazzzis@google.com</owner>
   <owner>src/components/blocked_content/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/content_creation/histograms.xml b/tools/metrics/histograms/metadata/content_creation/histograms.xml
index ee5099b..8ee7e74 100644
--- a/tools/metrics/histograms/metadata/content_creation/histograms.xml
+++ b/tools/metrics/histograms/metadata/content_creation/histograms.xml
@@ -354,7 +354,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.AsyncTask.SearchDuration" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>jeffreycohen@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml
index 9877d9ee..163a4d4 100644
--- a/tools/metrics/histograms/metadata/cras/histograms.xml
+++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -34,7 +34,7 @@
 </histogram>
 
 <histogram name="Cras.A2dp20msFailureOverStream" units="units"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -45,7 +45,7 @@
 </histogram>
 
 <histogram name="Cras.A2dpExitCode" enum="CrasA2dpExitCode"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -55,7 +55,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.Busyloop" units="units" expires_after="2022-11-20">
+<histogram name="Cras.Busyloop" units="units" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.TimePeriod" -->
 
@@ -138,7 +138,7 @@
   </token>
 </histogram>
 
-<histogram name="Cras.DeviceGain" units="level" expires_after="2022-11-20">
+<histogram name="Cras.DeviceGain" units="level" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.DeviceType" -->
 
@@ -221,7 +221,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceTypeInput" enum="CrasDeviceType"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -232,7 +232,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceTypeOutput" enum="CrasDeviceType"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -254,7 +254,7 @@
 </histogram>
 
 <histogram name="Cras.FetchDelayMilliSeconds" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.ClientType" and
      name="Cras.StreamType" -->
@@ -301,7 +301,7 @@
 </histogram>
 
 <histogram name="Cras.HfpWidebandSpeechPacketLoss" units="units"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="Cras.HfpWidebandSpeechSupported" enum="BooleanSupported"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -348,7 +348,7 @@
 </histogram>
 
 <histogram name="Cras.HighestInputHardwareLevel" units="frames"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -392,7 +392,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceBluetoothNarrowBandMicRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -492,7 +492,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceMicRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -569,7 +569,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceUSBRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -604,7 +604,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFirstTimeOutput" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -618,7 +618,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyAfterReschedulingInput"
-    units="count" expires_after="2022-11-20">
+    units="count" expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -629,7 +629,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyAfterReschedulingOutput"
-    units="count" expires_after="2022-11-20">
+    units="count" expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -641,7 +641,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyInput" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -652,7 +652,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyOutput" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -663,7 +663,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackSecondTimeInput" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -674,7 +674,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackSecondTimeOutput" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -685,7 +685,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceA2DPRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -730,7 +730,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHDMIRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -741,7 +741,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHeadphoneRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -774,7 +774,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceInternalSpeakerRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -818,7 +818,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceUSBRuntime" units="seconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -829,7 +829,7 @@
 </histogram>
 
 <histogram name="Cras.RtcDevicePair" enum="CrasDevicePair"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -925,7 +925,7 @@
 </histogram>
 
 <histogram name="Cras.StreamCallbackThreshold" units="frames"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -960,7 +960,7 @@
 </histogram>
 
 <histogram name="Cras.StreamConnectError" enum="CrasStreamConnectError"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -970,7 +970,7 @@
 </histogram>
 
 <histogram name="Cras.StreamCreateError" enum="CrasStreamCreateError"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>Record the errors happen when CRAS server creats a stream.</summary>
@@ -1002,7 +1002,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.StreamRuntime" units="seconds" expires_after="2022-11-20">
+<histogram name="Cras.StreamRuntime" units="seconds" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" and
@@ -1032,7 +1032,7 @@
 </histogram>
 
 <histogram name="Cras.StreamSamplingRate" units="bps"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -1057,7 +1057,7 @@
 </histogram>
 
 <histogram name="Cras.WebRTC.Audio.ApmCaptureInputLevelAverageRms"
-    units="dBFS (negated)" expires_after="2022-11-20">
+    units="dBFS (negated)" expires_after="2023-01-22">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cros_ml/histograms.xml b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
index b93b436..f9e49f0b 100644
--- a/tools/metrics/histograms/metadata/cros_ml/histograms.xml
+++ b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
@@ -166,7 +166,7 @@
 </histogram>
 
 <histogram name="MachineLearningService.PeakTotalMemoryKb" units="KB"
-    expires_after="2022-11-22">
+    expires_after="2023-01-22">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>honglinyu@chromium.org</owner>
@@ -225,7 +225,7 @@
 </histogram>
 
 <histogram name="MachineLearningService.TotalMemoryKb" units="KB"
-    expires_after="2022-11-22">
+    expires_after="2023-01-22">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>honglinyu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/crostini/histograms.xml b/tools/metrics/histograms/metadata/crostini/histograms.xml
index 97b763b8..95c77678 100644
--- a/tools/metrics/histograms/metadata/crostini/histograms.xml
+++ b/tools/metrics/histograms/metadata/crostini/histograms.xml
@@ -103,7 +103,7 @@
 </histogram>
 
 <histogram name="Crostini.Backup" enum="CrostiniExportContainerResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>Result of crostini backup.</summary>
@@ -180,7 +180,7 @@
 </histogram>
 
 <histogram name="Crostini.DiskResize.Result" enum="CrostiniDiskImageStatus"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
@@ -247,7 +247,7 @@
 </histogram>
 
 <histogram name="Crostini.FilesystemCorruption" enum="CorruptionStates"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>sidereal@google.com</owner>
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
@@ -402,7 +402,7 @@
 </histogram>
 
 <histogram name="Crostini.SetupResult" enum="CrostiniSetupResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
@@ -472,7 +472,7 @@
 </histogram>
 
 <histogram name="Crostini.Stability" enum="GuestOsFailureClasses"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
@@ -504,7 +504,7 @@
 </histogram>
 
 <histogram name="Crostini.TimeToInstallCancel" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
@@ -527,7 +527,7 @@
 </histogram>
 
 <histogram name="Crostini.TimeToInstallSuccess" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
@@ -552,7 +552,7 @@
 </histogram>
 
 <histogram name="Crostini.UninstallResult" enum="CrostiniUninstallResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cryptohome/histograms.xml b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
index ba0cdbd..8f6e625 100644
--- a/tools/metrics/histograms/metadata/cryptohome/histograms.xml
+++ b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
@@ -460,7 +460,7 @@
 </histogram>
 
 <histogram base="true" name="Cryptohome.LECredential"
-    enum="CryptohomeLECredError" expires_after="2022-11-20">
+    enum="CryptohomeLECredError" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="LECredentialOps" -->
 
   <owner>pmalani@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
index 01347af..dc401a0 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -424,7 +424,7 @@
 </histogram>
 
 <histogram name="CustomTabs.WarmupStateOnLaunch" enum="WarmupStateOnLaunch"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>lizeb@chromium.org</owner>
   <summary>
     Recorded only on Android. Reports whether warmup() has been called when a
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml
index 123f3e2..ab4c9db 100644
--- a/tools/metrics/histograms/metadata/download/histograms.xml
+++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -173,7 +173,7 @@
 </histogram>
 
 <histogram name="Download.CancelReason" enum="DownloadCancelReason"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>qinmin@chromium.org</owner>
   <owner>clank-downloads@google.com</owner>
   <summary>Records why the download is canceled.</summary>
@@ -678,7 +678,7 @@
 </histogram>
 
 <histogram base="true" name="Download.NetworkConnectionType.StartNew"
-    enum="NetworkConnectionType" expires_after="2022-11-13">
+    enum="NetworkConnectionType" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="DownloadSource" -->
 
   <owner>dtrainor@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 4fdddfa3..ebfd4d1 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -2319,7 +2319,7 @@
 </histogram>
 
 <histogram name="Enterprise.VpdUpdateStatus" units="units"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>igorcov@chromium.org</owner>
   <owner>tnagel@chromium.org</owner>
   <summary>
@@ -2470,7 +2470,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.IsManagedOrEnterpriseDevice"
-    enum="BooleanEnabled" expires_after="2022-11-20">
+    enum="BooleanEnabled" expires_after="2023-01-22">
   <owner>pastarmovj@chromium.org</owner>
   <owner>rogerta@chromium.org</owner>
   <owner>zmin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index 79028e9..e9b6ed6 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -958,7 +958,7 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollUpdate.JankyDurationPercentage" units="%"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ddrone@google.com</owner>
   <owner>chrometto-team@google.com</owner>
   <summary>
@@ -1520,7 +1520,7 @@
 </histogram>
 
 <histogram name="Event.PageShow.Persisted" enum="EventPageShowPersisted"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>hajimehoshi@chromium.org</owner>
   <owner>fergal@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 72ef683..699aa85 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -73,7 +73,7 @@
 </histogram>
 
 <histogram name="ExtensionBlacklist.UnblacklistInstalled"
-    enum="ExtensionLocation" expires_after="2022-11-18">
+    enum="ExtensionLocation" expires_after="2023-01-22">
   <owner>anunoy@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -124,7 +124,7 @@
 </histogram>
 
 <histogram name="Extensions.ActiveScriptController.DeniedExtensions"
-    units="Extension Count" expires_after="2022-10-23">
+    units="Extension Count" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -298,7 +298,7 @@
 </histogram>
 
 <histogram name="Extensions.Bindings.NativeBindingCreationTime"
-    units="microseconds" expires_after="2022-11-18">
+    units="microseconds" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -740,7 +740,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.RequestHeaderAdded"
-    enum="WebRequest.RequestHeader" expires_after="2022-11-20">
+    enum="WebRequest.RequestHeader" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -752,7 +752,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.RequestHeaderChanged"
-    enum="WebRequest.RequestHeader" expires_after="2022-11-20">
+    enum="WebRequest.RequestHeader" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -776,7 +776,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderAdded"
-    enum="WebRequest.ResponseHeader" expires_after="2022-11-14">
+    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -788,7 +788,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderChanged"
-    enum="WebRequest.ResponseHeader" expires_after="2022-11-20">
+    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -800,7 +800,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderRemoved"
-    enum="WebRequest.ResponseHeader" expires_after="2022-11-20">
+    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index 6bc99f3..d7beedd3 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -641,7 +641,7 @@
 </histogram>
 
 <histogram base="true" name="GPU.DirectComposition.DCLayerResult.Video"
-    enum="DCLayerResult" expires_after="2022-11-20">
+    enum="DCLayerResult" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="GPU.ProtectedVideoType" -->
 
   <owner>magchen@chromium.org</owner>
@@ -856,7 +856,7 @@
 </histogram>
 
 <histogram name="GPU.EstablishGpuChannelSyncTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>cduvall@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
@@ -1248,7 +1248,7 @@
 </histogram>
 
 <histogram name="GPU.PaintOpReader.DeserializationError"
-    enum="PaintOpDeserializationError" expires_after="2022-11-20">
+    enum="PaintOpDeserializationError" expires_after="2023-01-22">
   <owner>junov@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -1353,7 +1353,7 @@
 </histogram>
 
 <histogram name="Gpu.Rasterization.Raster.MSAASampleCountLog2" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>penghuang@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -1364,7 +1364,7 @@
 </histogram>
 
 <histogram name="Gpu.Rasterization.Raster.NumPaintOps" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>penghuang@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>Number of paint ops in a raster task.</summary>
@@ -1610,7 +1610,7 @@
 </histogram>
 
 <histogram name="GPU.Vulkan.PipelineCache.vkCreateGraphicsPipelines"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
   <owner>backer@chromium.org</owner>
   <owner>penghuang@chromium.org</owner>
   <owner>vasilyt@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index bcd8b67..abdf21ab 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="History.AttemptedToFixProfileError" units="units"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>sky@chromium.org</owner>
   <owner>sdefresne@chromium.org</owner>
   <component>UI&gt;Browser&gt;History</component>
@@ -555,7 +555,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Actions.InitialState"
-    enum="HistoryClustersInitialState" expires_after="2022-11-20">
+    enum="HistoryClustersInitialState" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -580,7 +580,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Actions.NumQueries"
-    units="number queries made" expires_after="2022-11-20">
+    units="number queries made" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -611,7 +611,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.BatchEntityLookupLatency2" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -625,7 +625,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.BatchEntityLookupSize" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -657,7 +657,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.ComputeClusters.ThreadTime"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -672,7 +672,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.EntityIdGathering.ThreadTime"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -687,7 +687,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.GetClustersLatency" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -789,7 +789,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.NumClustersReturned"
-    units="number clusters returned" expires_after="2022-11-20">
+    units="number clusters returned" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -820,7 +820,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.NumVisitsToCluster"
-    units="number visits" expires_after="2022-11-20">
+    units="number visits" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -850,7 +850,7 @@
 </histogram>
 
 <histogram name="History.Clusters.Backend.ProcessBatchOfVisits.ThreadTime"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -964,7 +964,7 @@
 </histogram>
 
 <histogram name="History.Clusters.ServiceLatency" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>tommycli@chromium.org</owner>
   <owner>chrome-journeys@google.com</owner>
   <component>UI&gt;Browser&gt;Journeys</component>
@@ -1451,7 +1451,7 @@
 </histogram>
 
 <histogram name="History.InitializationFailureStep" enum="HistoryInitStep"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>sky@chromium.org</owner>
   <owner>sdefresne@chromium.org</owner>
   <component>UI&gt;Browser&gt;History</component>
@@ -1787,7 +1787,7 @@
 </histogram>
 
 <histogram name="History.WeeklyURLCount" units="URLs"
-    expires_after="2022-09-11">
+    expires_after="2023-01-22">
   <owner>mpearson@chromium.org</owner>
   <owner>sky@chromium.org</owner>
   <component>UI&gt;Browser&gt;History</component>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index a3f595c..bd95fea7 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -215,7 +215,7 @@
 </histogram>
 
 <histogram name="Media.Audio.Capture.FramesProvided" units="frames"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>guidou@chromium.org</owner>
   <owner>armax@chromium.org</owner>
   <summary>
@@ -645,7 +645,7 @@
 </histogram>
 
 <histogram name="Media.Audio.InputStartupSuccessMac" enum="BooleanSuccess"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>henrika@chromium.org</owner>
   <owner>webrtc-audio@google.com</owner>
   <summary>
@@ -1332,7 +1332,7 @@
 </histogram>
 
 <histogram name="Media.AudioCapturerDroppedData" units="%"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>olka@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -1359,7 +1359,7 @@
 </histogram>
 
 <histogram name="Media.AudioCapturerMissedReadDeadline" units="%"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>olka@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -1597,7 +1597,7 @@
 </histogram>
 
 <histogram name="Media.AudioRendererAudioGlitches" enum="AudioGlitchResult"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>henrika@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1640,7 +1640,7 @@
 </histogram>
 
 <histogram name="Media.AudioRendererMissedDeadline" units="%"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>dalecurtis@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -1891,7 +1891,7 @@
 </histogram>
 
 <histogram name="Media.Controls.CTR" enum="MediaControlsCTREvent"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -2806,7 +2806,7 @@
 </histogram>
 
 <histogram name="Media.GpuArcVideoDecodeAccelerator.InstanceCount.All"
-    units="instances" expires_after="2022-11-20">
+    units="instances" expires_after="2023-01-22">
   <owner>andrescj@chromium.org</owner>
   <owner>chromeos-gfx-video@google.com</owner>
   <summary>
@@ -2816,7 +2816,7 @@
 </histogram>
 
 <histogram name="Media.GpuArcVideoDecodeAccelerator.InstanceCount.Initialized"
-    units="instances" expires_after="2022-11-20">
+    units="instances" expires_after="2023-01-22">
   <owner>andrescj@chromium.org</owner>
   <owner>chromeos-gfx-video@google.com</owner>
   <summary>
@@ -2829,7 +2829,7 @@
 </histogram>
 
 <histogram name="Media.GpuMemoryBufferVideoFramePool.OddOffset.Mappable"
-    enum="Boolean" expires_after="2022-11-20">
+    enum="Boolean" expires_after="2023-01-22">
   <owner>magchen@chromium.org</owner>
   <owner>ccameron@chromium.org</owner>
   <summary>
@@ -2879,7 +2879,7 @@
 </histogram>
 
 <histogram name="Media.GpuMemoryBufferVideoFramePool.UnsupportedFormat"
-    enum="VideoPixelFormatUnion" expires_after="2022-11-20">
+    enum="VideoPixelFormatUnion" expires_after="2023-01-22">
   <owner>magchen@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <summary>
@@ -4174,7 +4174,7 @@
 </histogram>
 
 <histogram name="Media.RtcLowLatencyVideoRenderer.MaxSizeDropQueueCount"
-    units="count" expires_after="2022-10-10">
+    units="count" expires_after="2023-01-22">
   <owner>kron@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
@@ -4384,7 +4384,7 @@
 </histogram>
 
 <histogram name="Media.Session.ActiveTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>steimel@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -5118,7 +5118,7 @@
 
 <histogram
     name="Media.VideoCapture.Windows.NumberOfRetriesNeededForMFGetDeviceStreamCategory"
-    units="retries" expires_after="2022-11-20">
+    units="retries" expires_after="2023-01-22">
   <owner>guidou@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -5855,7 +5855,7 @@
 </histogram>
 
 <histogram name="MediaRouter.CastStreaming.Session.Launch" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>takumif@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>Total time to launch a Cast Streaming mirror session.</summary>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 843e898c..68e00cc 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -2167,7 +2167,7 @@
 </histogram>
 
 <histogram name="Memory.ParkableString.OnDiskSizeKb.5min" units="KB"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>lizeb@chromium.org</owner>
   <owner>pasko@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 4a0a330..7a67b8a1 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -822,7 +822,7 @@
 </histogram>
 
 <histogram name="Navigation.MainFrameHasRTLDomain2" enum="Boolean"
-    expires_after="2022-10-12">
+    expires_after="2023-01-22">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -1326,7 +1326,7 @@
 </histogram>
 
 <histogram name="Navigation.UrlParamFilter.ClassificationListValidationResult"
-    enum="ClassificationListValidationResult" expires_after="2022-11-20">
+    enum="ClassificationListValidationResult" expires_after="2023-01-22">
   <owner>kaklilu@chromium.org</owner>
   <owner>src/chrome/browser/url_param_filter/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 5eb8208..c2a9d35 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -507,7 +507,7 @@
 </histogram>
 
 <histogram name="Net.CountOfBrokenAlternativeServices" units="services"
-    expires_after="2022-09-11">
+    expires_after="2023-01-22">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 1bf93194b..b264a1e 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -262,7 +262,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallationResult"
-    enum="NetworkCellularESimInstallResult" expires_after="2022-11-06">
+    enum="NetworkCellularESimInstallResult" expires_after="2023-01-22">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>jiajunz@google.com</owner>
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallViaQrCode.Result"
-    enum="HermesResponseStatus" expires_after="2022-11-06">
+    enum="HermesResponseStatus" expires_after="2023-01-22">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -2965,7 +2965,7 @@
 </histogram>
 
 <histogram name="NetworkService.DeletedOldCacheData" enum="Boolean"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>wfh@chromium.org</owner>
   <owner>mmenke@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index 5d78fb1..d65ef9b 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -56,7 +56,7 @@
 </histogram>
 
 <histogram name="NewTabPage.BackgroundService.Collections.RequestLatency"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
@@ -908,7 +908,7 @@
   </summary>
 </histogram>
 
-<histogram name="NewTabPage.Height" units="pixels" expires_after="2022-11-20">
+<histogram name="NewTabPage.Height" units="pixels" expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1074,7 +1074,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.Dismissed" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>mahmadi@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
@@ -1119,7 +1119,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.FreExplicitOptIn" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>pauladedeji@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1132,7 +1132,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.FreImplicitOptIn" enum="BooleanEnabled"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>pauladedeji@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1145,7 +1145,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.FreImpression" enum="BooleanEnabled"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>pauladedeji@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1158,7 +1158,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.FreLoaded" enum="BooleanEnabled"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>pauladedeji@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1423,7 +1423,7 @@
 </histogram>
 
 <histogram name="NewTabPage.OneGoogleBar.ShownTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
@@ -1569,7 +1569,7 @@
 </histogram>
 
 <histogram name="NewTabPage.RecipeTasks.RecipeClick" units="index"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>danpeng@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml
index 30cb555..67999d8 100644
--- a/tools/metrics/histograms/metadata/notifications/histograms.xml
+++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -28,7 +28,7 @@
 </variants>
 
 <histogram name="Notifications.Actions" enum="NotificationActionType"
-    expires_after="2022-11-22">
+    expires_after="2023-01-22">
   <owner>dewittj@chromium.org</owner>
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
@@ -654,7 +654,7 @@
 </histogram>
 
 <histogram name="Notifications.PerNotificationActions"
-    enum="NotificationActionType" expires_after="2022-11-22">
+    enum="NotificationActionType" expires_after="2023-01-22">
   <owner>dewittj@chromium.org</owner>
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index 226ba6b9..f606f382 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -1512,7 +1512,7 @@
 
 <histogram
     name="Omnibox.SearchPrefetch.SearchWhatYouTypedWasAlsoSuggested.History"
-    units="boolean" expires_after="2022-10-30">
+    units="boolean" expires_after="2023-01-22">
   <owner>ryansturm@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -1524,7 +1524,7 @@
 
 <histogram
     name="Omnibox.SearchPrefetch.SearchWhatYouTypedWasAlsoSuggested.HistoryOrSuggest"
-    units="boolean" expires_after="2022-10-30">
+    units="boolean" expires_after="2023-01-22">
   <owner>ryansturm@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
@@ -1536,7 +1536,7 @@
 
 <histogram
     name="Omnibox.SearchPrefetch.SearchWhatYouTypedWasAlsoSuggested.Suggest"
-    units="boolean" expires_after="2022-10-30">
+    units="boolean" expires_after="2023-01-22">
   <owner>ryansturm@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/oobe/histograms.xml b/tools/metrics/histograms/metadata/oobe/histograms.xml
index bd950e71..5857b3b 100644
--- a/tools/metrics/histograms/metadata/oobe/histograms.xml
+++ b/tools/metrics/histograms/metadata/oobe/histograms.xml
@@ -568,7 +568,7 @@
 </histogram>
 
 <histogram name="OOBE.WelcomeScreen.UserChangedLocale" enum="Boolean"
-    expires_after="2022-10-01">
+    expires_after="2023-01-22">
   <owner>bohdanty@google.com</owner>
   <owner>cros-oobe@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 7a23d54125..9317286b 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -174,7 +174,7 @@
 
 <histogram
     name="OptimizationGuide.EntityAnnotatorNativeLibrary.InitiatedSuccessfully"
-    enum="BooleanSuccess" expires_after="2022-11-20">
+    enum="BooleanSuccess" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -595,7 +595,7 @@
 
 <histogram
     name="OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached"
-    enum="BooleanCacheHit" expires_after="2022-11-20">
+    enum="BooleanCacheHit" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -680,7 +680,7 @@
 
 <histogram
     name="OptimizationGuide.PageContentAnnotationsService.ContentAnnotationsStorageMinMagnitudeForVisitNotFound"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -755,7 +755,7 @@
 
 <histogram
     name="OptimizationGuide.PageContentAnnotationsService.ModelExecutionLatency.PageEntities"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -767,7 +767,7 @@
 
 <histogram
     name="OptimizationGuide.PageContentAnnotationsService.ModelThreadExecutionLatency.PageEntities"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -809,7 +809,7 @@
 
 <histogram
     name="OptimizationGuide.PageEntitiesModelExecutor.CreatedSuccessfully"
-    enum="BooleanSuccess" expires_after="2022-11-20">
+    enum="BooleanSuccess" expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -821,7 +821,7 @@
 
 <histogram name="OptimizationGuide.PageEntitiesModelExecutor.CreationStatus"
     enum="OptimizationGuideEntityAnnotatorCreationStatus"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>sophiechang@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -893,7 +893,7 @@
 
 <histogram name="OptimizationGuide.PageTopicsOverrideList.FileLoadResult"
     enum="OptimizationGuidePageTopicsOverrideListFileLoadResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>robertogden@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -906,7 +906,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.PageTopicsOverrideList.GotFile"
-    enum="Boolean" expires_after="2022-11-20">
+    enum="Boolean" expires_after="2023-01-22">
   <owner>robertogden@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 7c9fdf90..fb8671a0 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3376,7 +3376,7 @@
 
 <histogram name="Conversions.AggregatableReport.AssembleReportStatus"
     enum="ConversionAssembleAggregatableReportStatus"
-    expires_after="2022-11-13">
+    expires_after="2023-01-22">
   <owner>linnan@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
@@ -3846,7 +3846,7 @@
 </histogram>
 
 <histogram name="Conversions.ReportRetrySucceed2" enum="BooleanSuccess"
-    expires_after="2022-10-23">
+    expires_after="2023-01-22">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <owner>linnan@chromium.org</owner>
@@ -3899,7 +3899,7 @@
 </histogram>
 
 <histogram name="Conversions.ReportSendOutcome3"
-    enum="ConversionReportSendOutcome" expires_after="2022-11-13">
+    enum="ConversionReportSendOutcome" expires_after="2023-01-22">
   <owner>linnan@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
@@ -4056,7 +4056,7 @@
 </histogram>
 
 <histogram name="Conversions.TriggerQueueEvents"
-    enum="ConversionTriggerQueueEvent" expires_after="2022-11-20">
+    enum="ConversionTriggerQueueEvent" expires_after="2023-01-22">
   <owner>apaseltiner@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
@@ -4527,7 +4527,8 @@
   </summary>
 </histogram>
 
-<histogram name="DemoMode.ActiveApp" enum="DemoModeApp" expires_after="M109">
+<histogram name="DemoMode.ActiveApp" enum="DemoModeApp"
+    expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4536,7 +4537,8 @@
   </summary>
 </histogram>
 
-<histogram name="DemoMode.AppLaunched" enum="DemoModeApp" expires_after="M109">
+<histogram name="DemoMode.AppLaunched" enum="DemoModeApp"
+    expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4547,7 +4549,7 @@
 </histogram>
 
 <histogram name="DemoMode.AppLaunchSource" enum="DemoModeAppLaunchSource"
-    expires_after="M109">
+    expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4556,7 +4558,7 @@
   </summary>
 </histogram>
 
-<histogram name="DemoMode.DwellTime" units="seconds" expires_after="M109">
+<histogram name="DemoMode.DwellTime" units="seconds" expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4568,7 +4570,7 @@
 </histogram>
 
 <histogram name="DemoMode.IdleLogoutWarningEvent"
-    enum="DemoModeIdleLogoutWarningEvent" expires_after="M109">
+    enum="DemoModeIdleLogoutWarningEvent" expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4606,7 +4608,8 @@
   </summary>
 </histogram>
 
-<histogram name="DemoMode.SessionLength" units="minutes" expires_after="M109">
+<histogram name="DemoMode.SessionLength" units="minutes"
+    expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -4662,7 +4665,7 @@
 </histogram>
 
 <histogram name="DemoMode.UniqueAppsLaunched" units="units"
-    expires_after="M109">
+    expires_after="2023-01-22">
   <owner>drcrash@chromium.org</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -5837,7 +5840,7 @@
 
 <histogram name="Feedback.HappinessTrackingSurvey.ShouldShowSurveyReason"
     enum="HappinessTrackingSurveyShouldShowSurveyReasons"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>sauski@google.com</owner>
   <owner>msramek@chromium.org</owner>
   <summary>
@@ -6753,7 +6756,7 @@
 </histogram>
 
 <histogram name="ImportantFile.FileReplaceRetryCount" units="attempt count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>brucedawson@chromium.org</owner>
   <owner>grt@chromium.org</owner>
   <summary>
@@ -7721,7 +7724,7 @@
 </histogram>
 
 <histogram name="Linux.SandboxStatus" enum="LinuxSandboxStatus"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mpdenton@google.com</owner>
   <owner>src/sandbox/linux/OWNERS</owner>
   <summary>
@@ -10858,7 +10861,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.GetFallbackFontsTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -10869,7 +10872,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.GetFallbackFontTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -10880,7 +10883,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.ShapeRunsFallback" enum="ShapeRunFallback"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -10890,7 +10893,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.ShapeRunsWithFallbackFontsTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -11481,7 +11484,7 @@
   </summary>
 </histogram>
 
-<histogram name="SB2.RemoteCall.Elapsed" units="ms" expires_after="2022-11-20">
+<histogram name="SB2.RemoteCall.Elapsed" units="ms" expires_after="2023-01-22">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -11723,7 +11726,7 @@
 </histogram>
 
 <histogram name="SBIRS.UploadResult" enum="ReportProcessingResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>caitkp@google.com</owner>
   <summary>
     The result of an attempted report upload by the safe browsing incident
@@ -12255,7 +12258,7 @@
 </histogram>
 
 <histogram name="SignedExchange.LoadResult2" enum="SignedExchangeLoadResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ksakamoto@chromium.org</owner>
   <owner>webpackage-dev@chromium.org</owner>
   <summary>
@@ -12533,7 +12536,7 @@
 </histogram>
 
 <histogram name="Skia.VulkanMemoryAllocator.AmountAllocated" units="KB"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>egdaniel@google.com</owner>
   <owner>bsalomon@google.com</owner>
   <summary>
@@ -14765,7 +14768,7 @@
 </histogram>
 
 <histogram name="WebFont.HadBlankText" enum="BooleanHadBlankText"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>kenjibaheux@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index f3a343ab..49ea945 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -189,7 +189,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.CompromisedBubble.CheckClicked"
-    enum="BooleanClicked" expires_after="2022-11-13">
+    enum="BooleanClicked" expires_after="2023-01-22">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -199,7 +199,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.CompromisedBubble.Type"
-    enum="PasswordBubbleFollowupType" expires_after="2022-11-13">
+    enum="PasswordBubbleFollowupType" expires_after="2023-01-22">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -335,7 +335,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AccountChooserDialogMultipleAccounts"
-    enum="AccountChooserDismissalReason" expires_after="2022-11-20">
+    enum="AccountChooserDismissalReason" expires_after="2023-01-22">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -345,7 +345,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AccountChooserDialogOneAccount"
-    enum="AccountChooserDismissalReason" expires_after="2022-11-20">
+    enum="AccountChooserDismissalReason" expires_after="2023-01-22">
   <owner>vasilii@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -867,7 +867,7 @@
 </histogram>
 
 <histogram name="PasswordManager.AutomaticChange.ForSitesWithScripts"
-    enum="PasswordCheckResolutionAction" expires_after="2022-11-20">
+    enum="PasswordCheckResolutionAction" expires_after="2023-01-22">
   <owner>kolos@chromium.org</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -1390,7 +1390,7 @@
 </histogram>
 
 <histogram name="PasswordManager.DynamicFormChanges" units="units"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -1580,7 +1580,7 @@
 </histogram>
 
 <histogram name="PasswordManager.HttpCredentials"
-    enum="PasswordManagerHttpCredentialType" expires_after="2022-11-20">
+    enum="PasswordManagerHttpCredentialType" expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1602,7 +1602,7 @@
 </histogram>
 
 <histogram name="PasswordManager.HttpPasswordMigrationMode"
-    enum="HttpPasswordMigrationMode" expires_after="2022-11-20">
+    enum="HttpPasswordMigrationMode" expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2102,7 +2102,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordDropdownShown"
-    enum="PasswordDropdownState" expires_after="2022-11-20">
+    enum="PasswordDropdownState" expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>Logs the state of the password dropdown when it's shown.</summary>
@@ -2712,7 +2712,7 @@
 </histogram>
 
 <histogram name="PasswordManager.RequirementsSpecFetcher.HttpResponseCode"
-    enum="HttpResponseCode" expires_after="2022-11-20">
+    enum="HttpResponseCode" expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -2760,7 +2760,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SavedGaiaPasswordHashCount" units="count"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>vsemeniuk@google.com</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -3249,7 +3249,7 @@
 </histogram>
 
 <histogram name="PasswordManager.UsernameDetectionMethod"
-    enum="UsernameDetectionMethod" expires_after="2022-11-20">
+    enum="UsernameDetectionMethod" expires_after="2023-01-22">
   <owner>kazinova@google.com</owner>
   <owner>kolos@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/payment/histograms.xml b/tools/metrics/histograms/metadata/payment/histograms.xml
index 1ecb4f9c..671f88d 100644
--- a/tools/metrics/histograms/metadata/payment/histograms.xml
+++ b/tools/metrics/histograms/metadata/payment/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="DigitalGoods.CrossSite" enum="Boolean"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>glenrob@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <owner>rouslan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index 17847cd..6ff3acf 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -695,7 +695,7 @@
 </histogram>
 
 <histogram name="Platform.MiniDiag.Launch" units="launches"
-    expires_after="2022-11-18">
+    expires_after="2023-01-22">
   <owner>roccochen@chromium.org</owner>
   <owner>chromeos-minidiag-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml
index 4043b14..34118087 100644
--- a/tools/metrics/histograms/metadata/printing/histograms.xml
+++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -138,7 +138,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.JobDuration.JobDone" units="ms"
-    expires_after="2022-10-23">
+    expires_after="2023-01-22">
   <owner>bmgordon@chromium.org</owner>
   <owner>project-bolton@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml
index fc4389f..fdd6af4 100644
--- a/tools/metrics/histograms/metadata/profile/histograms.xml
+++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -53,7 +53,7 @@
 </histogram>
 
 <histogram name="Profile.AllAccounts.Names" enum="ProfileAllAccountsNames"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -91,7 +91,7 @@
   <summary>The frequency of selection of each avatar.</summary>
 </histogram>
 
-<histogram name="Profile.BookmarksSize" units="MB" expires_after="2022-11-20">
+<histogram name="Profile.BookmarksSize" units="MB" expires_after="2023-01-22">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>Size of the bookmarks database.</summary>
@@ -250,7 +250,7 @@
 </histogram>
 
 <histogram name="Profile.Incognito.MainFrameNavigationsPerSession"
-    units="navigations" expires_after="2022-11-20">
+    units="navigations" expires_after="2023-01-22">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
   <summary>
@@ -465,7 +465,7 @@
 </histogram>
 
 <histogram name="Profile.NumberOfProfilesAtProfileSwitch" units="profiles"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>jkrcal@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -510,7 +510,7 @@
 </histogram>
 
 <histogram name="Profile.SessionDuration.PerProfile" enum="Profile"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>msarda@chromium.org</owner>
   <owner>alexilin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/quick_answers/histograms.xml b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
index ee5f2bf..815d8d6 100644
--- a/tools/metrics/histograms/metadata/quick_answers/histograms.xml
+++ b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
@@ -64,7 +64,7 @@
 </histogram>
 
 <histogram name="QuickAnswers.Click" enum="QuickAnswersResultType"
-    expires_after="2023-03-21">
+    expires_after="2023-01-22">
   <owner>updowndota@chromium.org</owner>
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml
index 53c8577..7cab144 100644
--- a/tools/metrics/histograms/metadata/renderer/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -328,7 +328,7 @@
 </histogram>
 
 <histogram name="Renderer.Font.SystemFallback.DomContentLoaded" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>kojii@chromium.org</owner>
   <owner>tkent@chromium.org</owner>
   <owner>yosin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 03248ea..d8facc1 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -185,7 +185,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.CheckBrowseUrl.HasLocalMatch"
-    enum="BooleanMatched" expires_after="2022-11-20">
+    enum="BooleanMatched" expires_after="2023-01-22">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -1859,7 +1859,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.Request.Size" units="bytes"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index a4522b2..dec28656 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -52,7 +52,7 @@
 </histogram>
 
 <histogram name="SBClientDownload.CheckDownloadStats.Exe"
-    enum="SBClientDownloadCheckDownloadStats" expires_after="2022-11-13">
+    enum="SBClientDownloadCheckDownloadStats" expires_after="2023-01-22">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/scanning/histograms.xml b/tools/metrics/histograms/metadata/scanning/histograms.xml
index ff4981c..e1f137b 100644
--- a/tools/metrics/histograms/metadata/scanning/histograms.xml
+++ b/tools/metrics/histograms/metadata/scanning/histograms.xml
@@ -84,7 +84,7 @@
 </histogram>
 
 <histogram name="Scanning.MultiPageScan.ToolbarAction"
-    enum="ScanMultiPageToolbarAction" expires_after="2022-11-20">
+    enum="ScanMultiPageToolbarAction" expires_after="2023-01-22">
   <owner>gavinwill@chromium.org</owner>
   <owner>cros-peripherals@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index 0dcc1a26..961da8ad 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -802,7 +802,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.ORB.BlockingReason"
-    enum="OrbBlockingDecisionReason" expires_after="2022-11-20">
+    enum="OrbBlockingDecisionReason" expires_after="2023-01-22">
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
   <summary>
@@ -813,7 +813,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.ORB.CorbVsOrb" enum="CorbVsOrb"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
   <summary>
@@ -827,7 +827,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.ORB.CorbVsOrb.OrbBlockedAndCorbDidnt.Reason"
-    enum="OrbBlockingDecisionReason" expires_after="2022-11-20">
+    enum="OrbBlockingDecisionReason" expires_after="2023-01-22">
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml
index e704348..499c167 100644
--- a/tools/metrics/histograms/metadata/service/histograms.xml
+++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -199,7 +199,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.CanMakePaymentEvent.Time" units="ms"
-    expires_after="2022-11-22">
+    expires_after="2023-01-22">
   <owner>rouslan@chromium.org</owner>
   <owner>web-payments-team@google.com</owner>
   <owner>jinho.bang@samsung.com</owner>
@@ -491,7 +491,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.ResponseReceivedToCompleted2"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>bashi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -507,7 +507,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.StartToForwardServiceWorker"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>bashi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -523,7 +523,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.WorkerReadyToFetchHandlerStart"
-    units="ms" expires_after="2022-11-20">
+    units="ms" expires_after="2023-01-22">
   <owner>bashi@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index fea2d12..7de029f 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -162,8 +162,8 @@
 </histogram>
 
 <histogram name="Settings.OpenSettingsFromMenu.PerProfileType"
-    enum="BrowserProfileType" expires_after="2022-08-02">
-  <owner>sideyilmaz@chromium.org</owner>
+    enum="BrowserProfileType" expires_after="2023-02-02">
+  <owner>roagarwal@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
   <summary>
     Records the profile type for opening the Settings page from menu.
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index 7eb090fa..2dcd4ea 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -410,7 +410,7 @@
 </histogram>
 
 <histogram name="Signin.Extensions.GetAuthTokenResult"
-    enum="GetAuthTokenResult" expires_after="2022-11-20">
+    enum="GetAuthTokenResult" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="GetAuthTokenType" -->
 
   <owner>alexilin@chromium.org</owner>
@@ -472,7 +472,7 @@
 </histogram>
 
 <histogram name="Signin.Intercept.HeuristicOutcome"
-    enum="SigninInterceptHeuristicOutcome" expires_after="2022-11-20">
+    enum="SigninInterceptHeuristicOutcome" expires_after="2023-01-22">
   <owner>droger@chromium.org</owner>
   <owner>alexilin@chromium.org</owner>
   <summary>
@@ -502,7 +502,7 @@
 </histogram>
 
 <histogram base="true" name="Signin.InterceptResult"
-    enum="SigninInterceptResult" expires_after="2022-11-20">
+    enum="SigninInterceptResult" expires_after="2023-01-22">
 <!-- Name completed by histogram_suffixes name="SigninInterceptType" -->
 
   <owner>alexilin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml
index 9ba21633..afeb79d 100644
--- a/tools/metrics/histograms/metadata/startup/histograms.xml
+++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -789,7 +789,7 @@
 </histogram>
 
 <histogram name="Startup.MobileSessionStartAction"
-    enum="MobileSessionStartAction" expires_after="2022-11-20">
+    enum="MobileSessionStartAction" expires_after="2023-01-22">
   <owner>thegreenfrog@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -869,7 +869,7 @@
 </histogram>
 
 <histogram name="Startup.PreMainMessageLoopRunImplLongTime" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>rkaplow@chromium.org</owner>
   <summary>
     The amount of time that elapsed during
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index d25675b..58feb82 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -580,7 +580,7 @@
 </histogram>
 
 <histogram name="Sync.ModelTypeBlockedDueToUndecryptableUpdate"
-    enum="SyncModelTypes" expires_after="2022-11-20">
+    enum="SyncModelTypes" expires_after="2023-01-22">
   <owner>victorvianna@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -909,7 +909,7 @@
 </histogram>
 
 <histogram name="Sync.PostedClientToServerMessageLatency" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
   <summary>
@@ -947,7 +947,7 @@
 </histogram>
 
 <histogram name="Sync.PostedGetUpdatesOrigin" enum="SyncGetUpdatesOrigin"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mastiz@chromium.org</owner>
   <owner>rushans@google.com</owner>
   <component>Services&gt;Sync</component>
@@ -1254,7 +1254,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultKeyRetrievalTrigger"
-    enum="TrustedVaultUserActionTrigger" expires_after="2022-11-20">
+    enum="TrustedVaultUserActionTrigger" expires_after="2023-01-22">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index cf259dd..fa68384 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -442,7 +442,7 @@
 </histogram>
 
 <histogram name="Tab.Preview.MemoryUsage.CompressedData.TotalKiB" units="KB"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>dfried@chromium.org</owner>
   <owner>collinbaker@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml
index 6413ad9..61cb9f4 100644
--- a/tools/metrics/histograms/metadata/translate/histograms.xml
+++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -480,7 +480,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.FinalTargetLanguage"
-    enum="LocaleCodeISO639" expires_after="2022-11-20">
+    enum="LocaleCodeISO639" expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -535,7 +535,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.InitialTargetLanguage"
-    enum="LocaleCodeISO639" expires_after="2022-11-20">
+    enum="LocaleCodeISO639" expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -644,7 +644,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.Ranker.Version" units="version"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -682,7 +682,7 @@
 </histogram>
 
 <histogram name="Translate.Ranker.Model.Status" enum="RankerModelStatus"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>rogerm@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -939,7 +939,7 @@
 </histogram>
 
 <histogram name="Translate.Translation.TargetLanguage" enum="LocaleCodeISO639"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -964,7 +964,7 @@
 </histogram>
 
 <histogram name="Translate.Translation.TimeToBeReady" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -977,7 +977,7 @@
 </histogram>
 
 <histogram name="Translate.Translation.TimeToLoad" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index fe3442e..11d5306 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -859,7 +859,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2023-01-15">
+    expires_after="2023-01-22">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index d75b4ad..84c0c20d 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -126,7 +126,7 @@
 </histogram>
 
 <histogram name="V8.CompileMicroSeconds" units="microseconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>yangguo@chromium.org</owner>
   <summary>
     Time spent in V8 compiler (full codegen) excluding parser.
@@ -295,7 +295,7 @@
 </histogram>
 
 <histogram name="V8.CompileScriptMicroSeconds.ProduceCache"
-    units="microseconds" expires_after="2022-11-20">
+    units="microseconds" expires_after="2023-01-22">
   <owner>leszeks@chromium.org</owner>
   <owner>v8-runtime@google.com</owner>
   <summary>
@@ -993,7 +993,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.GCCompactor" units="ms" expires_after="2022-11-20">
+<histogram name="V8.GCCompactor" units="ms" expires_after="2023-01-22">
   <owner>hpayer@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>Time spent in mark-sweep phase of GC.</summary>
@@ -1017,7 +1017,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.GCFinalizeMC" units="ms" expires_after="2022-11-20">
+<histogram name="V8.GCFinalizeMC" units="ms" expires_after="2023-01-22">
   <owner>mlippautz@chromium.org</owner>
   <owner>hpayer@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
@@ -1096,7 +1096,7 @@
 </histogram>
 
 <histogram name="V8.GCFinalizeMCReduceMemory" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mlippautz@chromium.org</owner>
   <owner>hpayer@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
@@ -1148,21 +1148,21 @@
 </histogram>
 
 <histogram name="V8.GCIncrementalMarkingReason" enum="GarbageCollectionReason"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mlippautz@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>Reason an incremental marking was started in V8.</summary>
 </histogram>
 
 <histogram name="V8.GCIncrementalMarkingStart" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hpayer@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>Time spent in starting incremental marking.</summary>
 </histogram>
 
 <histogram name="V8.GCIncrementalMarkingSum" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mlippautz@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>
@@ -1185,7 +1185,7 @@
 </histogram>
 
 <histogram name="V8.GCMarkCompactReason" enum="GarbageCollectionReason"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>mlippautz@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>Reason a mark-compact garbage collection was started in V8.</summary>
@@ -1674,7 +1674,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.WasmCatchCount" units="count" expires_after="2022-11-13">
+<histogram name="V8.WasmCatchCount" units="count" expires_after="2023-01-22">
   <owner>thibaudm@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
@@ -1764,7 +1764,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileModuleAsyncMicroSeconds" units="microseconds"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -2054,7 +2054,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.WasmReThrowCount" units="count" expires_after="2022-11-13">
+<histogram name="V8.WasmReThrowCount" units="count" expires_after="2023-01-22">
   <owner>thibaudm@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
@@ -2077,7 +2077,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.WasmThrowCount" units="count" expires_after="2022-11-20">
+<histogram name="V8.WasmThrowCount" units="count" expires_after="2023-01-22">
   <owner>thibaudm@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
@@ -2088,7 +2088,7 @@
 </histogram>
 
 <histogram name="V8.WasmTierUpModuleMicroSeconds" units="microseconds"
-    expires_after="2022-12-25">
+    expires_after="M106">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -2102,7 +2102,7 @@
 </histogram>
 
 <histogram name="V8.WasmTimeBetweenCatchMilliseconds" units="ms"
-    expires_after="2022-11-13">
+    expires_after="2023-01-22">
   <owner>thibaudm@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml
index 6ba8815..557b750c 100644
--- a/tools/metrics/histograms/metadata/variations/histograms.xml
+++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -302,7 +302,7 @@
 </histogram>
 
 <histogram name="Variations.ResourceRequestsAllowed"
-    enum="VariationsResourceRequestsAllowedState" expires_after="2022-11-20">
+    enum="VariationsResourceRequestsAllowedState" expires_after="2023-01-22">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -314,7 +314,7 @@
 </histogram>
 
 <histogram name="Variations.SafeMode.LoadSafeSeed.Result"
-    enum="VariationsSeedLoadResult" expires_after="2022-11-20">
+    enum="VariationsSeedLoadResult" expires_after="2023-01-22">
   <owner>isherman@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -328,7 +328,7 @@
 </histogram>
 
 <histogram name="Variations.SafeMode.LoadSafeSeed.SignatureValidity"
-    enum="VariationSeedSignature" expires_after="2022-11-20">
+    enum="VariationSeedSignature" expires_after="2023-01-22">
   <owner>isherman@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -342,7 +342,7 @@
 </histogram>
 
 <histogram name="Variations.SafeMode.StoreSafeSeed.Result"
-    enum="VariationsSeedStoreResult" expires_after="2022-11-20">
+    enum="VariationsSeedStoreResult" expires_after="2023-01-22">
   <owner>isherman@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -355,7 +355,7 @@
 </histogram>
 
 <histogram name="Variations.SafeMode.StoreSafeSeed.SignatureValidity"
-    enum="VariationSeedSignature" expires_after="2022-11-20">
+    enum="VariationSeedSignature" expires_after="2023-01-22">
   <owner>isherman@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -439,7 +439,7 @@
 </histogram>
 
 <histogram name="Variations.SeedDateChange" enum="VariationsSeedDateChange"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>jwd@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -539,7 +539,7 @@
 </histogram>
 
 <histogram name="Variations.SeedStoreResult" enum="VariationsSeedStoreResult"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -550,7 +550,7 @@
 </histogram>
 
 <histogram name="Variations.SeedUsage" enum="VariationsSeedUsage"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>caitlinfischer@google.com</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -615,7 +615,7 @@
 </histogram>
 
 <histogram name="Variations.StoreSeed.DataSize" units="KiB"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>asvitkine@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/web_audio/histograms.xml b/tools/metrics/histograms/metadata/web_audio/histograms.xml
index 900765f..623aa5b 100644
--- a/tools/metrics/histograms/metadata/web_audio/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_audio/histograms.xml
@@ -230,7 +230,7 @@
 </histogram>
 
 <histogram name="WebAudio.ConvolverNode.ImpulseResponseLength" units="ms"
-    expires_after="2022-11-13">
+    expires_after="2023-01-22">
   <owner>hongchan@chromium.org</owner>
   <owner>mjwilson@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index 36683f8..6b54d59 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -427,7 +427,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.AudioInterruptionMs" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hlundin@chromium.org</owner>
   <owner>ivoc@chromium.org</owner>
   <summary>
@@ -580,7 +580,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.Clockdrift" enum="ClockdriftLevel"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>gustaf@chromium.org</owner>
   <owner>peah@chromium.org</owner>
   <summary>
@@ -590,7 +590,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.DelayChanges"
-    enum="WebRTCEventFrequency" expires_after="2022-11-20">
+    enum="WebRTCEventFrequency" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -660,7 +660,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MaxCaptureJitter"
-    units="frames (10 ms)" expires_after="2022-11-20">
+    units="frames (10 ms)" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -670,7 +670,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MaxRenderJitter"
-    units="frames (10 ms)" expires_after="2022-11-20">
+    units="frames (10 ms)" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -697,7 +697,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MinCaptureJitter"
-    units="frames (10 ms)" expires_after="2022-11-20">
+    units="frames (10 ms)" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -707,7 +707,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.MinRenderJitter"
-    units="frames (10 ms)" expires_after="2022-11-20">
+    units="frames (10 ms)" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>gustaf@chromium.org</owner>
   <summary>
@@ -755,7 +755,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.EchoCanceller.RenderOverruns"
-    enum="WebRTCEventFrequency" expires_after="2022-11-20">
+    enum="WebRTCEventFrequency" expires_after="2023-01-22">
   <owner>peah@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <summary>
@@ -790,7 +790,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.Encoder.CodecType" enum="WebRtcAudioCodecs"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>aleloi@chromium.org</owner>
   <summary>
     Histogram of audio codec usage. Every sample corresponds to 5 seconds of
@@ -852,7 +852,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.TargetBitrateInKbps" units="kbps"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>hlundin@chromium.org</owner>
   <summary>
     The target bitrate in kbps that the audio codec should try to produce on
@@ -916,7 +916,7 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.InitialBandwidthEstimate" units="kbps"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>holmer@chromium.org</owner>
   <summary>The bandwidth estimate 2 seconds into a WebRTC call.</summary>
 </histogram>
@@ -1208,7 +1208,7 @@
 </histogram>
 
 <histogram name="WebRTC.DesktopCapture.Win.DesktopCapturerImpl"
-    enum="WebRtcDesktopCapturerImpl" expires_after="2022-11-20">
+    enum="WebRtcDesktopCapturerImpl" expires_after="2023-01-22">
   <owner>jamiewalch@chromium.org</owner>
   <owner>auorion@microsoft.com</owner>
   <owner>edgecapabilitiesdev@microsoft.com</owner>
@@ -1265,7 +1265,7 @@
 </histogram>
 
 <histogram name="WebRTC.DesktopCaptureCounters" enum="DesktopCaptureCounters"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>toprice@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
@@ -2085,7 +2085,7 @@
 </histogram>
 
 <histogram name="WebRTC.SentVideoTrackDuration" units="ms"
-    expires_after="2022-11-20">
+    expires_after="2023-01-22">
   <owner>perkj@chromium.org</owner>
   <summary>
     Durations of video tracks sent over a PeerConnection. The stopwatch starts
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 4413e64..f7b2fb2 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "2248c20cf6d98c436292ae961f87060d7099a4cb",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/e4d93e430c4751cda91e9fb5603154a6d44314fd/trace_processor_shell.exe"
+            "hash": "094b7fabf4f387985e67fc19585af2c5eb6a7d7b",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/bc18be5bc39f7674d27aef6b042d0a0caa117d58/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "7d5b49130f6e3ec1627783ab5c2908adcf70def8",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/e4d93e430c4751cda91e9fb5603154a6d44314fd/trace_processor_shell"
+            "hash": "deb70e7acf8b89f7bb65b3a383288c7ccacbf32a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/e19e4f253f28cfb21c5a2c2587c98b77b978bb98/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "6618ebd430cb56e06fdd328970e63dab9b06dfdd",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/e19e4f253f28cfb21c5a2c2587c98b77b978bb98/trace_processor_shell"
+            "hash": "3910b83d4c8654e16e9bc0bd0aae85ef2a7adad0",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/880ad9da29099b0d8b0e1a2e3cdd3794b25b18b9/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/scripts/annotation_tools.py b/tools/traffic_annotation/scripts/annotation_tools.py
index 71a867f..fe23dd4 100644
--- a/tools/traffic_annotation/scripts/annotation_tools.py
+++ b/tools/traffic_annotation/scripts/annotation_tools.py
@@ -127,8 +127,10 @@
 
     # Change directory to src (two levels upper than build path).
     os.chdir(os.path.join(self.build_path, "..", ".."))
-    command = subprocess.Popen(args, stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE)
+    command = subprocess.Popen(args,
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE,
+                               encoding="utf-8")
     stdout_text, stderr_text = command.communicate()
 
     if stderr_text:
diff --git a/tools/traffic_annotation/scripts/check_annotations.py b/tools/traffic_annotation/scripts/check_annotations.py
index cf048454..2072d320 100755
--- a/tools/traffic_annotation/scripts/check_annotations.py
+++ b/tools/traffic_annotation/scripts/check_annotations.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2017 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.
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index e9f9cfea..596a6ad 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -379,7 +379,7 @@
  <item id="pending_beacon_api" added_in_milestone="105" content_hash_code="02288864" os_list="linux,windows,android,chromeos" file_path="content/browser/renderer_host/pending_beacon_service.cc" />
  <item id="printing_server_printers_query" added_in_milestone="106" content_hash_code="06f4759c" os_list="chromeos" file_path="chrome/browser/ash/printing/server_printers_fetcher.cc" />
  <item id="download_bubble_retry_download" added_in_milestone="105" content_hash_code="000b1439" os_list="linux,windows,chromeos" file_path="chrome/browser/download/bubble/download_bubble_controller.cc" />
- <item id="quick_answers_loader" added_in_milestone="105" content_hash_code="01dd7d56" os_list="chromeos" file_path="chromeos/components/quick_answers/result_loader.cc" />
- <item id="chrome_search_suggest_service" added_in_milestone="105" content_hash_code="04d973c6" os_list="linux,windows,android" file_path="components/search/start_suggest_service.cc" />
+ <item id="quick_answers_loader" added_in_milestone="105" content_hash_code="070b3239" os_list="chromeos" file_path="chromeos/components/quick_answers/result_loader.cc" />
+ <item id="chrome_search_suggest_service" added_in_milestone="105" content_hash_code="04d973c6" os_list="linux,windows,android,chromeos" file_path="components/search/start_suggest_service.cc" />
  <item id="coupon_persisted_tab_data" added_in_milestone="105" content_hash_code="006dcd97" os_list="android" file_path="chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java" />
 </annotations>
diff --git a/tools/typescript/definitions/passwords_private.d.ts b/tools/typescript/definitions/passwords_private.d.ts
index c1230fc..490a82a 100644
--- a/tools/typescript/definitions/passwords_private.d.ts
+++ b/tools/typescript/definitions/passwords_private.d.ts
@@ -83,6 +83,13 @@
         link: string;
       }
 
+      export interface CompromisedInfo {
+        compromiseTime: number;
+        elapsedTimeSinceCompromise: string;
+        compromiseType: CompromiseType;
+        isMuted: boolean;
+      }
+
       export interface PasswordUiEntry {
         urls: UrlCollection;
         username: string;
@@ -92,6 +99,9 @@
         storedIn: PasswordStoreSet;
         isAndroidCredential: boolean;
         note: string;
+        changePasswordUrl?: string;
+        hasStartableScript: boolean;
+        compromisedInfo?: CompromisedInfo;
       }
 
       export interface ExceptionEntry {
@@ -104,24 +114,6 @@
         folderName?: string;
       }
 
-      export interface CompromisedInfo {
-        compromiseTime: number;
-        elapsedTimeSinceCompromise: string;
-        compromiseType: CompromiseType;
-        isMuted: boolean;
-      }
-
-      export interface InsecureCredential {
-        id: number;
-        urls: UrlCollection;
-        isAndroidCredential: boolean;
-        changePasswordUrl?: string;
-        hasStartableScript: boolean;
-        username: string;
-        password?: string;
-        compromisedInfo?: CompromisedInfo;
-      }
-
       export interface PasswordCheckStatus {
         state: PasswordCheckState;
         alreadyProcessed?: number;
@@ -168,23 +160,15 @@
           callback: (isOptedIn: boolean) => void): void;
       export function optInForAccountStorage(optIn: boolean): void;
       export function getCompromisedCredentials(
-          callback: (credentials: Array<InsecureCredential>) => void): void;
+          callback: (credentials: Array<PasswordUiEntry>) => void): void;
       export function getWeakCredentials(
-          callback: (credentials: Array<InsecureCredential>) => void): void;
-      export function getPlaintextInsecurePassword(
-          credential: InsecureCredential, reason: PlaintextReason,
-          callback: (credential: InsecureCredential) => void): void;
-      export function changeInsecureCredential(
-          credential: InsecureCredential, newPassword: string,
-          callback?: () => void): void;
-      export function removeInsecureCredential(
-          credential: InsecureCredential, callback?: () => void): void;
+          callback: (credentials: Array<PasswordUiEntry>) => void): void;
       export function muteInsecureCredential(
-          credential: InsecureCredential, callback?: () => void): void;
+          credential: PasswordUiEntry, callback?: () => void): void;
       export function unmuteInsecureCredential(
-          credential: InsecureCredential, callback?: () => void): void;
+          credential: PasswordUiEntry, callback?: () => void): void;
       export function recordChangePasswordFlowStarted(
-          credential: InsecureCredential, isManualFlow: boolean): void;
+          credential: PasswordUiEntry, isManualFlow: boolean): void;
       export function refreshScriptsIfNecessary(
           callback?: () => void): void;
       export function startPasswordCheck(callback?: () => void): void;
@@ -192,7 +176,7 @@
       export function getPasswordCheckStatus(
           callback: (status: PasswordCheckStatus) => void): void;
       export function startAutomatedPasswordChange(
-          credential: InsecureCredential,
+          credential: PasswordUiEntry,
           callback?: (success: boolean) => void): void;
       export function isAccountStoreDefault(
           callback: (isDefault: boolean) => void): void;
@@ -210,9 +194,9 @@
       export const onAccountStorageOptInStateChanged:
           ChromeEvent<(optInState: boolean) => void>;
       export const onCompromisedCredentialsChanged:
-          ChromeEvent<(credentials: Array<InsecureCredential>) => void>;
+          ChromeEvent<(credentials: Array<PasswordUiEntry>) => void>;
       export const onWeakCredentialsChanged:
-          ChromeEvent<(credentials: Array<InsecureCredential>) => void>;
+          ChromeEvent<(credentials: Array<PasswordUiEntry>) => void>;
       export const onPasswordCheckStatusChanged:
           ChromeEvent<(status: PasswordCheckStatus) => void>;
     }
diff --git a/ui/file_manager/file_manager/common/js/filtered_volume_manager.js b/ui/file_manager/file_manager/common/js/filtered_volume_manager.js
index d0f2533..b9bb92e 100644
--- a/ui/file_manager/file_manager/common/js/filtered_volume_manager.js
+++ b/ui/file_manager/file_manager/common/js/filtered_volume_manager.js
@@ -184,7 +184,7 @@
    * @return {boolean}
    * @private
    */
-  isFuseBoxFileSystem(diskFileSystemType) {
+  isFuseBoxFileSystem_(diskFileSystemType) {
     return diskFileSystemType === 'fusebox';
   }
 
@@ -195,7 +195,7 @@
    * @return {boolean}
    * @private
    */
-  isMediaStoreVolume(volumeInfo) {
+  isMediaStoreVolume_(volumeInfo) {
     return MEDIA_STORE_VOLUME_TYPES.indexOf(volumeInfo.volumeType) >= 0;
   }
 
@@ -217,7 +217,7 @@
 
     // If the media store filter is enabled and the volume is not supported
     // by the Android MediaStore, remove the volume from the UI.
-    if (this.isMediaStoreOnly_ && !this.isMediaStoreVolume(volumeInfo)) {
+    if (this.isMediaStoreOnly_ && !this.isMediaStoreVolume_(volumeInfo)) {
       return false;
     }
 
@@ -229,9 +229,9 @@
     } else if (this.isFuseBoxOnly_) {
       // SelectFileAsh requires native volumes. Note: DocumentsProvider and
       // FSPs return false here, until they are implemented in the fusebox.
-      return this.isFuseBoxFileSystem(volumeInfo.diskFileSystemType) ||
+      return this.isFuseBoxFileSystem_(volumeInfo.diskFileSystemType) ||
           VolumeManagerCommon.VolumeType.isNative(volumeInfo.volumeType);
-    } else if (this.isFuseBoxFileSystem(volumeInfo.diskFileSystemType)) {
+    } else if (this.isFuseBoxFileSystem_(volumeInfo.diskFileSystemType)) {
       // Normal Files app: remove fusebox volumes.
       return false;
     }
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h
index 307efc1a..fd5f5c1 100644
--- a/ui/gfx/gpu_memory_buffer.h
+++ b/ui/gfx/gpu_memory_buffer.h
@@ -27,8 +27,6 @@
 #include "base/android/scoped_hardware_buffer_handle.h"
 #endif
 
-extern "C" typedef struct _ClientBuffer* ClientBuffer;
-
 namespace base {
 namespace trace_event {
 class ProcessMemoryDump;
@@ -135,9 +133,6 @@
   // caller takes ownership of the returned handle.
   virtual GpuMemoryBufferHandle CloneHandle() const = 0;
 
-  // Type-checking downcast routine.
-  virtual ClientBuffer AsClientBuffer() = 0;
-
   // Dumps information about the memory backing the GpuMemoryBuffer to |pmd|.
   // The memory usage is attributed to |buffer_dump_guid|.
   // |tracing_process_id| uniquely identifies the process owning the memory.